// File: epfml[P]Bi-Sent2Vec/src/fasttext.cc
// Function: fasttext::FastText::train(std::shared_ptr<fasttext::Args>)
void FastText::train(std::shared_ptr<Args> args) {
  args_ = args;
  dict_ = std::make_shared<Dictionary>(args_);
  if (args_->input == "-") {
    // manage expectations
    std::cerr << "Cannot use stdin for training!" << std::endl;
    exit(EXIT_FAILURE);
  }
  std::ifstream ifs(args_->input);
  if (!ifs.is_open()) {
    std::cerr << "Input file cannot be opened!" << std::endl;
    exit(EXIT_FAILURE);
  }
  dict_->readFromFile(ifs);
  ifs.close();

  if (args_->pretrainedVectors.size() != 0) {
    loadVectors(args_->pretrainedVectors);
    loadOutputVectors(args_->pretrainedVectors);
  } else {
    input_ = std::make_shared<Matrix>(dict_->nwords()+args_->bucket+args_->bucketChar, args_->dim);
    input_->uniform(1.0 / args_->dim);
    output_ = std::make_shared<Matrix>(dict_->nwords(), args_->dim);
    output_->zero();
  }

  start = clock();
  tokenCount = 0;
  if (args_->thread > 1) {
    std::vector<std::thread> threads;
    for (int32_t i = 0; i < args_->thread; i++) {
      threads.push_back(std::thread([=]() { trainThread(i); }));
    }
    for (auto it = threads.begin(); it != threads.end(); ++it) {
      it->join();
    }
  } else {
    trainThread(0);
  }
  model_ = std::make_shared<Model>(input_, output_, args_, 0);

  saveModel();
  saveVectors();
  if (args_->saveOutput > 0) {
    saveOutput();
  }

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x370, %rsp            # imm = 0x370
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x310(%rbp)
callq 0x236a0
movq -0x310(%rbp), %rsi
leaq -0x20(%rbp), %rdi
callq 0x34350
movq -0x310(%rbp), %rdi
addq $0x10, %rdi
leaq -0x20(%rbp), %rsi
callq 0x343c0
leaq -0x20(%rbp), %rdi
callq 0x343f0
movq -0x310(%rbp), %rdi
callq 0xe6e0
movq %rax, %rdi
leaq 0x11ea2(%rip), %rsi     # 0x43958
callq 0x7cc0
testb $0x1, %al
jne 0x31ac1
jmp 0x31aed
movq 0x2d528(%rip), %rdi     # 0x5eff0
leaq 0x11e8b(%rip), %rsi     # 0x4395a
callq 0x5420
movq %rax, %rdi
movq 0x2d4b2(%rip), %rsi     # 0x5ef90
callq 0x5460
movl $0x1, %edi
callq 0x54f0
movq -0x310(%rbp), %rdi
callq 0xe6e0
movq %rax, %rsi
leaq -0x228(%rbp), %rdi
movq %rdi, -0x320(%rbp)
movl $0x8, %edx
callq 0x56d0
movq -0x320(%rbp), %rdi
callq 0x56c0
movb %al, -0x311(%rbp)
jmp 0x31b28
movb -0x311(%rbp), %al
testb $0x1, %al
jne 0x31b86
jmp 0x31b34
movq 0x2d4b5(%rip), %rdi     # 0x5eff0
leaq 0x11e37(%rip), %rsi     # 0x43979
callq 0x5420
movq %rax, -0x328(%rbp)
jmp 0x31b50
movq -0x328(%rbp), %rdi
movq 0x2d432(%rip), %rsi     # 0x5ef90
callq 0x5460
jmp 0x31b65
movl $0x1, %edi
callq 0x54f0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
jmp 0x320b4
movq -0x310(%rbp), %rdi
addq $0x10, %rdi
callq 0x34050
movq %rax, %rdi
leaq -0x228(%rbp), %rsi
callq 0x92c0
jmp 0x31ba7
leaq -0x228(%rbp), %rdi
callq 0x50f0
jmp 0x31bb5
movq -0x310(%rbp), %rdi
callq 0xe6e0
movq %rax, %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x5300
cmpq $0x0, %rax
je 0x31caf
movq -0x310(%rbp), %rdi
callq 0xe6e0
movq %rax, %rsi
addq $0x108, %rsi            # imm = 0x108
leaq -0x258(%rbp), %rdi
callq 0x51d0
jmp 0x31bfe
movq -0x310(%rbp), %rdi
leaq -0x258(%rbp), %rsi
callq 0x305a0
jmp 0x31c13
leaq -0x258(%rbp), %rdi
callq 0x58d8
movq -0x310(%rbp), %rdi
callq 0xe6e0
movq %rax, %rsi
addq $0x108, %rsi            # imm = 0x108
leaq -0x278(%rbp), %rdi
callq 0x51d0
jmp 0x31c43
movq -0x310(%rbp), %rdi
leaq -0x278(%rbp), %rsi
callq 0x30be0
jmp 0x31c58
leaq -0x278(%rbp), %rdi
callq 0x58d8
jmp 0x31e56
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
leaq -0x258(%rbp), %rdi
callq 0x58d8
jmp 0x320b4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
leaq -0x278(%rbp), %rdi
callq 0x58d8
jmp 0x320b4
movq -0x310(%rbp), %rdi
addq $0x10, %rdi
callq 0x34050
movq %rax, %rdi
callq 0x8340
movl %eax, -0x32c(%rbp)
jmp 0x31ccf
movq -0x310(%rbp), %rdi
callq 0xe6e0
movq -0x310(%rbp), %rdi
movq %rax, %rcx
movl -0x32c(%rbp), %eax
movl 0xc4(%rcx), %ecx
addl %ecx, %eax
movl %eax, -0x330(%rbp)
callq 0xe6e0
movq -0x310(%rbp), %rdi
movq %rax, %rcx
movl -0x330(%rbp), %eax
movl 0xc8(%rcx), %ecx
addl %ecx, %eax
movl %eax, -0x28c(%rbp)
callq 0xe6e0
movq %rax, %rdx
addq $0x94, %rdx
leaq -0x288(%rbp), %rdi
leaq -0x28c(%rbp), %rsi
callq 0x356c0
jmp 0x31d40
movq -0x310(%rbp), %rdi
addq $0x20, %rdi
movq %rdi, -0x340(%rbp)
leaq -0x288(%rbp), %rsi
movq %rsi, -0x348(%rbp)
callq 0x34480
movq -0x348(%rbp), %rdi
callq 0x23810
movq -0x340(%rbp), %rdi
callq 0x235f0
movq -0x310(%rbp), %rdi
movq %rax, -0x338(%rbp)
callq 0xe6e0
movq -0x338(%rbp), %rdi
cvtsi2sdl 0x94(%rax), %xmm1
movsd 0x10b11(%rip), %xmm0    # 0x428b8
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
callq 0x1e020
jmp 0x31db6
movq -0x310(%rbp), %rdi
addq $0x10, %rdi
callq 0x34050
movq %rax, %rdi
callq 0x8340
movl %eax, -0x34c(%rbp)
jmp 0x31dd6
movq -0x310(%rbp), %rdi
movl -0x34c(%rbp), %eax
movl %eax, -0x2a4(%rbp)
callq 0xe6e0
movq %rax, %rdx
addq $0x94, %rdx
leaq -0x2a0(%rbp), %rdi
leaq -0x2a4(%rbp), %rsi
callq 0x356c0
jmp 0x31e0d
movq -0x310(%rbp), %rdi
addq $0x30, %rdi
movq %rdi, -0x358(%rbp)
leaq -0x2a0(%rbp), %rsi
movq %rsi, -0x360(%rbp)
callq 0x34480
movq -0x360(%rbp), %rdi
callq 0x23810
movq -0x358(%rbp), %rdi
callq 0x235f0
movq %rax, %rdi
callq 0x1dfc0
jmp 0x31e54
jmp 0x31e56
callq 0x52e0
movq -0x310(%rbp), %rdi
movq %rax, 0x78(%rdi)
addq $0x70, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x348f0
movq -0x310(%rbp), %rdi
callq 0xe6e0
cmpl $0x1, 0xd4(%rax)
jle 0x31fee
leaq -0x2c0(%rbp), %rdi
callq 0x34980
movl $0x0, -0x2c4(%rbp)
movq -0x310(%rbp), %rdi
movl -0x2c4(%rbp), %eax
movl %eax, -0x364(%rbp)
callq 0xe6e0
movq %rax, %rcx
movl -0x364(%rbp), %eax
cmpl 0xd4(%rcx), %eax
jge 0x31f6a
movq -0x310(%rbp), %rax
movq %rax, -0x2e0(%rbp)
movl -0x2c4(%rbp), %eax
movl %eax, -0x2d8(%rbp)
leaq -0x2d0(%rbp), %rdi
leaq -0x2e0(%rbp), %rsi
callq 0x320d0
jmp 0x31efe
leaq -0x2c0(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
callq 0x349a0
jmp 0x31f13
leaq -0x2d0(%rbp), %rdi
callq 0x349d0
movl -0x2c4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c4(%rbp)
jmp 0x31ea2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
jmp 0x31fdd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
leaq -0x2d0(%rbp), %rdi
callq 0x349d0
jmp 0x31fdd
leaq -0x2c0(%rbp), %rdi
callq 0x34a00
movq %rax, -0x2e8(%rbp)
leaq -0x2c0(%rbp), %rdi
callq 0x34a70
movq %rax, -0x2f0(%rbp)
leaq -0x2e8(%rbp), %rdi
leaq -0x2f0(%rbp), %rsi
callq 0x34a30
testb $0x1, %al
jne 0x31fa9
jmp 0x31fcf
leaq -0x2e8(%rbp), %rdi
callq 0x34aa0
movq %rax, %rdi
callq 0x5750
jmp 0x31fbf
jmp 0x31fc1
leaq -0x2e8(%rbp), %rdi
callq 0x34ac0
jmp 0x31f7d
leaq -0x2c0(%rbp), %rdi
callq 0x34ae0
jmp 0x32000
leaq -0x2c0(%rbp), %rdi
callq 0x34ae0
jmp 0x320b4
movq -0x310(%rbp), %rdi
xorl %esi, %esi
callq 0x2fdf0
jmp 0x31ffe
jmp 0x32000
movq -0x310(%rbp), %rcx
movq %rcx, %rsi
addq $0x20, %rsi
movq %rcx, %rdx
addq $0x30, %rdx
movl $0x0, -0x304(%rbp)
leaq -0x300(%rbp), %rdi
leaq -0x304(%rbp), %r8
callq 0x34550
jmp 0x32034
movq -0x310(%rbp), %rdi
addq $0x60, %rdi
leaq -0x300(%rbp), %rsi
movq %rsi, -0x370(%rbp)
callq 0x345e0
movq -0x370(%rbp), %rdi
callq 0x34610
movq -0x310(%rbp), %rdi
callq 0x28f90
jmp 0x3206c
movq -0x310(%rbp), %rdi
callq 0x28020
jmp 0x3207a
movq -0x310(%rbp), %rdi
callq 0xe6e0
cmpl $0x0, 0x128(%rax)
jle 0x3209f
movq -0x310(%rbp), %rdi
callq 0x28800
jmp 0x3209d
jmp 0x3209f
leaq -0x228(%rbp), %rdi
callq 0x5130
addq $0x370, %rsp            # imm = 0x370
popq %rbp
retq
leaq -0x228(%rbp), %rdi
callq 0x5130
movq -0x230(%rbp), %rdi
callq 0x57a0
nopl (%rax)