// File: ddu1[P]polarizedtext/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();

// set dim to number of labels (ddu)
  if( args_->model == model_name::pwv) { 
    args_->dim = dict_->nlabels();
  }

  if (args_->model == model_name::sup) {
    output_ = std::make_shared<Matrix>(dict_->nlabels(), args_->dim);
  } else {
    output_ = std::make_shared<Matrix>(dict_->nwords(), args_->dim);
  }

  //input_->uniform(1.0 / args_->dim);
  //output_->zero();

  // initialized vectors with labels (ddu)
  auto words = dict_->getWords();
  output_->zero();

    if (args_->pretrainedVectors.size() != 0) {
        loadVectors(args_->pretrainedVectors);
    } else {

        input_ = std::make_shared<Matrix>(dict_->nwords()+args_->bucket, args_->dim);
        if(args_->model == model_name::pwv ) {
          input_->zero();
          for( int32_t i = 0; i < dict_->nwords(); ++i) { // for words
            int32_t non_zero_size = words[i].nlabels;
            Vector vec = Vector(args_->dim, dict_->getLabels(i));
            input_->addRow(vec, i, non_zero_size? (1.0/non_zero_size): 0);
          }
          for( int32_t i = 0; i < args_->bucket; ++i) { // for buckets (subwords)
            Vector ones = Vector(args_->dim);
            ones.ones();
            input_->addRow(ones, dict_->nwords()+i, 1.0 / args_->dim);
          }
        }
        else {
          input_->uniform(1.0 / args_->dim);
        }  
    }

  start = clock();
  tokenCount = 0;
  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();
  }
  model_ = std::make_shared<Model>(input_, output_, args_, 0);

  saveModel();
  if (args_->model != model_name::sup) {
    saveVectors();
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x400, %rsp            # imm = 0x400
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x368(%rbp)
callq 0x9ea0
movq -0x368(%rbp), %rsi
leaq -0x20(%rbp), %rdi
callq 0x20090
movq -0x368(%rbp), %rdi
addq $0x10, %rdi
leaq -0x20(%rbp), %rsi
callq 0x20100
leaq -0x20(%rbp), %rdi
callq 0x20130
movq -0x368(%rbp), %rdi
callq 0xa170
movq %rax, %rdi
leaq 0xac06(%rip), %rsi      # 0x29e4c
callq 0x62c0
testb $0x1, %al
jne 0x1f251
jmp 0x1f27d
movq 0x1cd98(%rip), %rdi     # 0x3bff0
leaq 0xabef(%rip), %rsi      # 0x29e4e
callq 0x42e0
movq %rax, %rdi
movq 0x1cd2a(%rip), %rsi     # 0x3bf98
callq 0x4310
movl $0x1, %edi
callq 0x4390
movq -0x368(%rbp), %rdi
callq 0xa170
movq %rax, %rsi
leaq -0x228(%rbp), %rdi
movq %rdi, -0x378(%rbp)
movl $0x8, %edx
callq 0x4510
movq -0x378(%rbp), %rdi
callq 0x4500
movb %al, -0x369(%rbp)
jmp 0x1f2b8
movb -0x369(%rbp), %al
testb $0x1, %al
jne 0x1f316
jmp 0x1f2c4
movq 0x1cd25(%rip), %rdi     # 0x3bff0
leaq 0xab9b(%rip), %rsi      # 0x29e6d
callq 0x42e0
movq %rax, -0x380(%rbp)
jmp 0x1f2e0
movq -0x380(%rbp), %rdi
movq 0x1ccaa(%rip), %rsi     # 0x3bf98
callq 0x4310
jmp 0x1f2f5
movl $0x1, %edi
callq 0x4390
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
jmp 0x1fbb8
movq -0x368(%rbp), %rdi
addq $0x10, %rdi
callq 0x1ff50
movq %rax, %rdi
leaq -0x228(%rbp), %rsi
callq 0x7750
jmp 0x1f337
leaq -0x228(%rbp), %rdi
callq 0x4080
jmp 0x1f345
movq -0x368(%rbp), %rdi
callq 0xa170
cmpl $0x4, 0x8c(%rax)
jne 0x1f38f
movq -0x368(%rbp), %rdi
addq $0x10, %rdi
callq 0x1ff50
movq %rax, %rdi
callq 0x6b90
movl %eax, -0x384(%rbp)
jmp 0x1f37a
movq -0x368(%rbp), %rdi
callq 0xa170
movl -0x384(%rbp), %ecx
movl %ecx, 0x6c(%rax)
movq -0x368(%rbp), %rdi
callq 0xa170
cmpl $0x3, 0x8c(%rax)
jne 0x1f41d
movq -0x368(%rbp), %rdi
addq $0x10, %rdi
callq 0x1ff50
movq %rax, %rdi
callq 0x6b90
movl %eax, -0x388(%rbp)
jmp 0x1f3c4
movq -0x368(%rbp), %rdi
movl -0x388(%rbp), %eax
movl %eax, -0x24c(%rbp)
callq 0xa170
movq %rax, %rdx
addq $0x6c, %rdx
leaq -0x248(%rbp), %rdi
leaq -0x24c(%rbp), %rsi
callq 0x20aa0
jmp 0x1f3f8
movq -0x368(%rbp), %rdi
addq $0x30, %rdi
leaq -0x248(%rbp), %rsi
callq 0x201c0
leaq -0x248(%rbp), %rdi
callq 0x159f0
jmp 0x1f494
movq -0x368(%rbp), %rdi
addq $0x10, %rdi
callq 0x1ff50
movq %rax, %rdi
callq 0x6b70
movl %eax, -0x38c(%rbp)
jmp 0x1f43d
movq -0x368(%rbp), %rdi
movl -0x38c(%rbp), %eax
movl %eax, -0x264(%rbp)
callq 0xa170
movq %rax, %rdx
addq $0x6c, %rdx
leaq -0x260(%rbp), %rdi
leaq -0x264(%rbp), %rsi
callq 0x20aa0
jmp 0x1f471
movq -0x368(%rbp), %rdi
addq $0x30, %rdi
leaq -0x260(%rbp), %rsi
callq 0x201c0
leaq -0x260(%rbp), %rdi
callq 0x159f0
movq -0x368(%rbp), %rdi
addq $0x10, %rdi
callq 0x1ff50
movq %rax, %rdi
callq 0x6bd0
movq %rax, -0x398(%rbp)
jmp 0x1f4b5
movq -0x398(%rbp), %rsi
leaq -0x280(%rbp), %rdi
callq 0x20b40
jmp 0x1f4ca
movq -0x368(%rbp), %rdi
addq $0x30, %rdi
callq 0x15820
movq %rax, %rdi
callq 0x12a90
jmp 0x1f4e4
movq -0x368(%rbp), %rdi
callq 0xa170
movq %rax, %rdi
addq $0xd0, %rdi
callq 0x4200
cmpq $0x0, %rax
je 0x1f58d
movq -0x368(%rbp), %rdi
callq 0xa170
movq %rax, %rsi
addq $0xd0, %rsi
leaq -0x2a0(%rbp), %rdi
callq 0x4100
jmp 0x1f52d
movq -0x368(%rbp), %rdi
leaq -0x2a0(%rbp), %rsi
callq 0x1ec40
jmp 0x1f542
leaq -0x2a0(%rbp), %rdi
callq 0x4688
jmp 0x1f97f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
jmp 0x1fbac
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
leaq -0x2a0(%rbp), %rdi
callq 0x4688
jmp 0x1fbac
movq -0x368(%rbp), %rdi
addq $0x10, %rdi
callq 0x1ff50
movq %rax, %rdi
callq 0x6b70
movl %eax, -0x39c(%rbp)
jmp 0x1f5ad
movq -0x368(%rbp), %rdi
callq 0xa170
movq -0x368(%rbp), %rdi
movq %rax, %rcx
movl -0x39c(%rbp), %eax
movl 0x90(%rcx), %ecx
addl %ecx, %eax
movl %eax, -0x2b4(%rbp)
callq 0xa170
movq %rax, %rdx
addq $0x6c, %rdx
leaq -0x2b0(%rbp), %rdi
leaq -0x2b4(%rbp), %rsi
callq 0x20aa0
jmp 0x1f5f8
movq -0x368(%rbp), %rdi
addq $0x20, %rdi
leaq -0x2b0(%rbp), %rsi
callq 0x201c0
leaq -0x2b0(%rbp), %rdi
callq 0x159f0
movq -0x368(%rbp), %rdi
callq 0xa170
cmpl $0x4, 0x8c(%rax)
jne 0x1f935
movq -0x368(%rbp), %rdi
addq $0x20, %rdi
callq 0x15820
movq %rax, %rdi
callq 0x12a90
jmp 0x1f64e
movl $0x0, -0x2b8(%rbp)
movq -0x368(%rbp), %rdi
movl -0x2b8(%rbp), %eax
movl %eax, -0x3a4(%rbp)
addq $0x10, %rdi
callq 0x1ff50
movq %rax, %rdi
callq 0x6b70
movl %eax, -0x3a0(%rbp)
jmp 0x1f684
movl -0x3a4(%rbp), %eax
movl -0x3a0(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1f802
movslq -0x2b8(%rbp), %rsi
leaq -0x280(%rbp), %rdi
callq 0xa2b0
movq -0x368(%rbp), %rdi
movsbl 0x48(%rax), %eax
movl %eax, -0x2bc(%rbp)
callq 0xa170
movq -0x368(%rbp), %rdi
movslq 0x6c(%rax), %rax
movq %rax, -0x3b0(%rbp)
addq $0x10, %rdi
callq 0x1ff50
movq %rax, %rsi
movl -0x2b8(%rbp), %edx
leaq -0x2e8(%rbp), %rdi
callq 0x6bf0
jmp 0x1f6f3
movq -0x3b0(%rbp), %rsi
leaq -0x2d0(%rbp), %rdi
leaq -0x2e8(%rbp), %rdx
callq 0x13090
jmp 0x1f70f
leaq -0x2e8(%rbp), %rdi
callq 0xa040
movq -0x368(%rbp), %rdi
addq $0x20, %rdi
callq 0x15820
movq %rax, -0x3c0(%rbp)
movslq -0x2b8(%rbp), %rax
movq %rax, -0x3b8(%rbp)
cmpl $0x0, -0x2bc(%rbp)
je 0x1f767
cvtsi2sdl -0x2bc(%rbp), %xmm1
movsd 0x9e6f(%rip), %xmm0     # 0x295c8
divsd %xmm1, %xmm0
movsd %xmm0, -0x3c8(%rbp)
jmp 0x1f774
xorps %xmm0, %xmm0
movsd %xmm0, -0x3c8(%rbp)
jmp 0x1f774
movq -0x3b8(%rbp), %rdx
movq -0x3c0(%rbp), %rdi
movsd -0x3c8(%rbp), %xmm0
cvtsd2ss %xmm0, %xmm0
leaq -0x2d0(%rbp), %rsi
callq 0x12ba0
jmp 0x1f79c
leaq -0x2d0(%rbp), %rdi
callq 0x131d0
movl -0x2b8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2b8(%rbp)
jmp 0x1f658
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
leaq -0x2e8(%rbp), %rdi
callq 0xa040
jmp 0x1fbac
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
leaq -0x2d0(%rbp), %rdi
callq 0x131d0
jmp 0x1fbac
movl $0x0, -0x2ec(%rbp)
movq -0x368(%rbp), %rdi
movl -0x2ec(%rbp), %eax
movl %eax, -0x3cc(%rbp)
callq 0xa170
movq %rax, %rcx
movl -0x3cc(%rbp), %eax
cmpl 0x90(%rcx), %eax
jge 0x1f933
movq -0x368(%rbp), %rdi
callq 0xa170
movslq 0x6c(%rax), %rsi
leaq -0x300(%rbp), %rdi
callq 0x13030
jmp 0x1f857
leaq -0x300(%rbp), %rdi
callq 0x13220
jmp 0x1f865
movq -0x368(%rbp), %rdi
addq $0x20, %rdi
callq 0x15820
movq -0x368(%rbp), %rdi
movq %rax, -0x3d8(%rbp)
addq $0x10, %rdi
callq 0x1ff50
movq %rax, %rdi
callq 0x6b70
movl %eax, -0x3d0(%rbp)
jmp 0x1f89c
movq -0x368(%rbp), %rdi
movl -0x3d0(%rbp), %eax
movl -0x2ec(%rbp), %ecx
addl %ecx, %eax
cltq
movq %rax, -0x3e0(%rbp)
callq 0xa170
movq -0x3d8(%rbp), %rdi
movq -0x3e0(%rbp), %rdx
cvtsi2sdl 0x6c(%rax), %xmm1
movsd 0x9cee(%rip), %xmm0     # 0x295c8
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
leaq -0x300(%rbp), %rsi
callq 0x12ba0
jmp 0x1f8f0
leaq -0x300(%rbp), %rdi
callq 0x131d0
movl -0x2ec(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2ec(%rbp)
jmp 0x1f80c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
leaq -0x300(%rbp), %rdi
callq 0x131d0
jmp 0x1fbac
jmp 0x1f97d
movq -0x368(%rbp), %rdi
addq $0x20, %rdi
callq 0x15820
movq -0x368(%rbp), %rdi
movq %rax, -0x3e8(%rbp)
callq 0xa170
movq -0x3e8(%rbp), %rdi
cvtsi2sdl 0x6c(%rax), %xmm1
movsd 0x9c5c(%rip), %xmm0     # 0x295c8
divsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
callq 0x12af0
jmp 0x1f97b
jmp 0x1f97d
jmp 0x1f97f
callq 0x41e0
movq -0x368(%rbp), %rdi
movq %rax, 0x58(%rdi)
addq $0x50, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x20c30
leaq -0x318(%rbp), %rdi
callq 0x20cc0
movl $0x0, -0x31c(%rbp)
movq -0x368(%rbp), %rdi
movl -0x31c(%rbp), %eax
movl %eax, -0x3ec(%rbp)
callq 0xa170
movq %rax, %rcx
movl -0x3ec(%rbp), %eax
cmpl 0x9c(%rcx), %eax
jge 0x1fa7d
movq -0x368(%rbp), %rax
movq %rax, -0x338(%rbp)
movl -0x31c(%rbp), %eax
movl %eax, -0x330(%rbp)
leaq -0x328(%rbp), %rdi
leaq -0x338(%rbp), %rsi
callq 0x1fbd0
jmp 0x1fa0e
leaq -0x318(%rbp), %rdi
leaq -0x328(%rbp), %rsi
callq 0x20ce0
jmp 0x1fa23
leaq -0x328(%rbp), %rdi
callq 0x20d10
movl -0x31c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x31c(%rbp)
jmp 0x1f9b2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
jmp 0x1fba0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
leaq -0x328(%rbp), %rdi
callq 0x20d10
jmp 0x1fba0
leaq -0x318(%rbp), %rdi
callq 0x20d40
movq %rax, -0x340(%rbp)
leaq -0x318(%rbp), %rdi
callq 0x20db0
movq %rax, -0x348(%rbp)
leaq -0x340(%rbp), %rdi
leaq -0x348(%rbp), %rsi
callq 0x20d70
testb $0x1, %al
jne 0x1fabc
jmp 0x1fae2
leaq -0x340(%rbp), %rdi
callq 0x20de0
movq %rax, %rdi
callq 0x4570
jmp 0x1fad2
jmp 0x1fad4
leaq -0x340(%rbp), %rdi
callq 0x20e00
jmp 0x1fa90
movq -0x368(%rbp), %rcx
movq %rcx, %rsi
addq $0x20, %rsi
movq %rcx, %rdx
addq $0x30, %rdx
movl $0x0, -0x35c(%rbp)
leaq -0x358(%rbp), %rdi
leaq -0x35c(%rbp), %r8
callq 0x201f0
jmp 0x1fb16
movq -0x368(%rbp), %rdi
addq $0x40, %rdi
leaq -0x358(%rbp), %rsi
movq %rsi, -0x3f8(%rbp)
callq 0x20280
movq -0x3f8(%rbp), %rdi
callq 0x202b0
movq -0x368(%rbp), %rdi
callq 0x1c980
jmp 0x1fb4e
movq -0x368(%rbp), %rdi
callq 0xa170
cmpl $0x3, 0x8c(%rax)
je 0x1fb73
movq -0x368(%rbp), %rdi
callq 0x1c630
jmp 0x1fb71
jmp 0x1fb73
leaq -0x318(%rbp), %rdi
callq 0x20e20
leaq -0x280(%rbp), %rdi
callq 0x9fe0
leaq -0x228(%rbp), %rdi
callq 0x4090
addq $0x400, %rsp            # imm = 0x400
popq %rbp
retq
leaq -0x318(%rbp), %rdi
callq 0x20e20
leaq -0x280(%rbp), %rdi
callq 0x9fe0
leaq -0x228(%rbp), %rdi
callq 0x4090
movq -0x230(%rbp), %rdi
callq 0x45b0