// File: epfml[P]sent2vec/src/fasttext.cc
// Function: fasttext::FastText::cbowCWNgrams(fasttext::Model&, float, std::vector<int, std::allocator<int>>&)
void FastText::cbowCWNgrams(Model& model, real lr, std::vector<int32_t>& line){
  if (line.size() <= 1) return;
  std::vector<int32_t> subsLine, sidx2lidx;
  subsLine.reserve(line.size());
  sidx2lidx.reserve(line.size());
  std::uniform_real_distribution<> uniformSub(0, 1);
  for (int32_t i=0; i < line.size(); ++i) {
    if (uniformSub(model.rng) > dict_->getPDiscard(line[i]) || dict_->getTokenCount(line[i]) < args_->minCountLabel) {
      continue;
    }
    subsLine.push_back(line[i]);
    sidx2lidx.push_back(i);
  }
  std::vector<int32_t> bow;
  std::uniform_int_distribution<> uniform(1, args_->ws);
  for (int32_t w = 0; w < subsLine.size(); w++) {
    int32_t boundary = uniform(model.rng);
    bow.clear();
    for (int32_t c = -boundary; c <= boundary; c++) {
      if (c != 0 && w + c >= 0 && w + c < subsLine.size()) {
        const std::vector<int32_t>& ngrams = dict_->getNgrams(subsLine[w + c]);
        bow.insert(bow.end(), ngrams.cbegin(), ngrams.cend());
      }
    }
    int32_t start = std::max(0, w - boundary);
    int32_t end = std::min(int32_t(subsLine.size())-1, w + boundary);
    if (start == end) continue;
    int32_t buff = line[sidx2lidx[w]];
    line[sidx2lidx[w]] = 0;
    dict_->addNgrams(bow, line, sidx2lidx[start], sidx2lidx[end], args_->wordNgrams, args_->dropoutK, model.rng); // add word ngrams to bow
    line[sidx2lidx[w]] = buff;
    model.update(bow, subsLine[w], lr, args_->boostNgrams, dict_->nwords(), dict_->nwords() + args_->bucket);
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x200, %rsp            # imm = 0x200
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movss %xmm0, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x20(%rbp), %rdi
callq 0xf0e0
cmpq $0x1, %rax
ja 0x2b27b
jmp 0x2b979
leaq -0x38(%rbp), %rdi
movq %rdi, -0x108(%rbp)
callq 0xe7d0
leaq -0x50(%rbp), %rdi
callq 0xe7d0
movq -0x20(%rbp), %rdi
callq 0xf0e0
movq -0x108(%rbp), %rdi
movq %rax, %rsi
callq 0x34790
jmp 0x2b2ae
movq -0x20(%rbp), %rdi
callq 0xf0e0
movq %rax, %rsi
leaq -0x50(%rbp), %rdi
callq 0x34790
jmp 0x2b2c5
leaq -0x70(%rbp), %rdi
xorps %xmm0, %xmm0
movsd 0x1765c(%rip), %xmm1    # 0x42930
callq 0xf400
jmp 0x2b2db
movl $0x0, -0x74(%rbp)
movslq -0x74(%rbp), %rax
movq %rax, -0x110(%rbp)
movq -0x20(%rbp), %rdi
callq 0xf0e0
movq %rax, %rcx
movq -0x110(%rbp), %rax
cmpq %rcx, %rax
jae 0x2b427
movq -0x10(%rbp), %rsi
addq $0x110, %rsi            # imm = 0x110
leaq -0x70(%rbp), %rdi
callq 0xf500
movsd %xmm0, -0x118(%rbp)
jmp 0x2b327
movq -0x100(%rbp), %rdi
addq $0x10, %rdi
callq 0x33af0
movq %rax, -0x128(%rbp)
movq -0x20(%rbp), %rdi
movslq -0x74(%rbp), %rsi
callq 0xe5d0
movq -0x128(%rbp), %rdi
movl (%rax), %esi
callq 0x92d0
movss %xmm0, -0x11c(%rbp)
jmp 0x2b363
movsd -0x118(%rbp), %xmm0
movss -0x11c(%rbp), %xmm1
cvtss2sd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
ja 0x2b3da
movq -0x100(%rbp), %rdi
addq $0x10, %rdi
callq 0x33af0
movq %rax, -0x138(%rbp)
movq -0x20(%rbp), %rdi
movslq -0x74(%rbp), %rsi
callq 0xe5d0
movq -0x138(%rbp), %rdi
movl (%rax), %esi
callq 0x9240
movq %rax, -0x130(%rbp)
jmp 0x2b3b8
movq -0x100(%rbp), %rdi
callq 0xea70
movq %rax, %rcx
movq -0x130(%rbp), %rax
movslq 0xac(%rcx), %rcx
cmpq %rcx, %rax
jge 0x2b3ed
jmp 0x2b419
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x2b982
movq -0x20(%rbp), %rdi
movslq -0x74(%rbp), %rsi
callq 0xe5d0
movq %rax, %rsi
leaq -0x38(%rbp), %rdi
callq 0xe960
jmp 0x2b408
leaq -0x50(%rbp), %rdi
leaq -0x74(%rbp), %rsi
callq 0xe960
jmp 0x2b417
jmp 0x2b419
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x2b2e2
leaq -0x90(%rbp), %rdi
callq 0xe7d0
movq -0x100(%rbp), %rdi
callq 0xea70
movl 0x98(%rax), %edx
leaq -0x98(%rbp), %rdi
movl $0x1, %esi
callq 0xf2a0
jmp 0x2b458
movl $0x0, -0x9c(%rbp)
movslq -0x9c(%rbp), %rax
movq %rax, -0x140(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xf0e0
movq %rax, %rcx
movq -0x140(%rbp), %rax
cmpq %rcx, %rax
jae 0x2b95b
movq -0x10(%rbp), %rsi
addq $0x110, %rsi            # imm = 0x110
leaq -0x98(%rbp), %rdi
callq 0xf2d0
movl %eax, -0x144(%rbp)
jmp 0x2b4ab
movl -0x144(%rbp), %eax
movl %eax, -0xa0(%rbp)
leaq -0x90(%rbp), %rdi
callq 0xe920
xorl %eax, %eax
subl -0xa0(%rbp), %eax
movl %eax, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
cmpl -0xa0(%rbp), %eax
jg 0x2b64c
cmpl $0x0, -0xa4(%rbp)
je 0x2b636
movl -0x9c(%rbp), %eax
addl -0xa4(%rbp), %eax
cmpl $0x0, %eax
jl 0x2b636
movl -0x9c(%rbp), %eax
addl -0xa4(%rbp), %eax
cltq
movq %rax, -0x150(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xf0e0
movq %rax, %rcx
movq -0x150(%rbp), %rax
cmpq %rcx, %rax
jae 0x2b636
movq -0x100(%rbp), %rdi
addq $0x10, %rdi
callq 0x33af0
movq %rax, -0x160(%rbp)
movl -0x9c(%rbp), %eax
movl -0xa4(%rbp), %ecx
addl %ecx, %eax
movslq %eax, %rsi
leaq -0x38(%rbp), %rdi
callq 0xe5d0
movq -0x160(%rbp), %rdi
movl (%rax), %esi
callq 0x85a0
movq %rax, -0x158(%rbp)
jmp 0x2b57e
movq -0x158(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0x90(%rbp), %rdi
movq %rdi, -0x170(%rbp)
callq 0xedd0
movq %rax, -0xc0(%rbp)
leaq -0xb8(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0xfbd0
movq -0xb0(%rbp), %rdi
callq 0xf700
movq %rax, -0xc8(%rbp)
movq -0xb0(%rbp), %rdi
callq 0xf770
movq -0x170(%rbp), %rdi
movq %rax, -0xd0(%rbp)
movq -0xb8(%rbp), %rsi
movq -0xc8(%rbp), %rdx
movq -0xd0(%rbp), %rcx
callq 0x346e0
movq %rax, -0x168(%rbp)
jmp 0x2b609
movq -0x168(%rbp), %rax
movq %rax, -0xd8(%rbp)
jmp 0x2b636
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x90(%rbp), %rdi
callq 0xe8c0
jmp 0x2b982
jmp 0x2b638
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x2b4d1
movl $0x0, -0xe0(%rbp)
movl -0x9c(%rbp), %eax
movl -0xa0(%rbp), %ecx
subl %ecx, %eax
movl %eax, -0xe4(%rbp)
leaq -0xe0(%rbp), %rdi
leaq -0xe4(%rbp), %rsi
callq 0x34890
movq %rax, -0x178(%rbp)
jmp 0x2b686
movq -0x178(%rbp), %rax
movl (%rax), %eax
movl %eax, -0xdc(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xf0e0
decl %eax
movl %eax, -0xec(%rbp)
movl -0x9c(%rbp), %eax
movl -0xa0(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0xf0(%rbp)
leaq -0xec(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x1d9d0
movq %rax, -0x180(%rbp)
jmp 0x2b6d6
movq -0x180(%rbp), %rax
movl (%rax), %eax
movl %eax, -0xe8(%rbp)
movl -0xdc(%rbp), %eax
cmpl -0xe8(%rbp), %eax
jne 0x2b6f8
jmp 0x2b947
movq -0x20(%rbp), %rax
movq %rax, -0x1b8(%rbp)
movslq -0x9c(%rbp), %rsi
leaq -0x50(%rbp), %rdi
movq %rdi, -0x1a8(%rbp)
callq 0xe5d0
movq -0x1b8(%rbp), %rdi
movslq (%rax), %rsi
callq 0xe5d0
movq -0x1a8(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0xf4(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x1b0(%rbp)
movslq -0x9c(%rbp), %rsi
callq 0xe5d0
movq -0x1b0(%rbp), %rdi
movslq (%rax), %rsi
callq 0xe5d0
movq -0x100(%rbp), %rdi
movl $0x0, (%rax)
addq $0x10, %rdi
callq 0x33af0
movq -0x1a8(%rbp), %rdi
movq %rax, -0x1a0(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x198(%rbp)
movslq -0xdc(%rbp), %rsi
callq 0xe5d0
movq -0x1a8(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x18c(%rbp)
movslq -0xe8(%rbp), %rsi
callq 0xe5d0
movq -0x100(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x188(%rbp)
callq 0xea70
movq -0x100(%rbp), %rdi
movl 0xb4(%rax), %eax
movl %eax, -0x184(%rbp)
callq 0xea70
movq -0x1a0(%rbp), %rdi
movq -0x198(%rbp), %rdx
movl -0x18c(%rbp), %ecx
movl -0x188(%rbp), %r8d
movl -0x184(%rbp), %r9d
movl 0x9c(%rax), %esi
movq -0x10(%rbp), %r10
addq $0x110, %r10            # imm = 0x110
movq %rsp, %rax
movq %r10, 0x8(%rax)
movl %esi, (%rax)
leaq -0x90(%rbp), %rsi
callq 0xa3e0
jmp 0x2b82a
movl -0xf4(%rbp), %eax
movl %eax, -0x1d4(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x1e0(%rbp)
movslq -0x9c(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0xe5d0
movq -0x1e0(%rbp), %rdi
movslq (%rax), %rsi
callq 0xe5d0
movl -0x1d4(%rbp), %ecx
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movq %rax, -0x1d0(%rbp)
movslq -0x9c(%rbp), %rsi
leaq -0x38(%rbp), %rdi
callq 0xe5d0
movq -0x100(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x1c8(%rbp)
movss -0x14(%rbp), %xmm0
movss %xmm0, -0x1c4(%rbp)
callq 0xea70
movq -0x100(%rbp), %rdi
movsd 0x88(%rax), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, -0x1c0(%rbp)
addq $0x10, %rdi
callq 0x33af0
movq %rax, %rdi
callq 0x8540
movl %eax, -0x1bc(%rbp)
jmp 0x2b8d8
movq -0x100(%rbp), %rdi
addq $0x10, %rdi
callq 0x33af0
movq %rax, %rdi
callq 0x8540
movl %eax, -0x1e4(%rbp)
jmp 0x2b8f8
movq -0x100(%rbp), %rdi
callq 0xea70
movl -0x1e4(%rbp), %r8d
movq -0x1d0(%rbp), %rdi
movl -0x1c8(%rbp), %edx
movss -0x1c4(%rbp), %xmm0
movss -0x1c0(%rbp), %xmm1
movl -0x1bc(%rbp), %ecx
movl 0xc4(%rax), %eax
addl %eax, %r8d
leaq -0x90(%rbp), %rsi
callq 0x22f70
jmp 0x2b945
jmp 0x2b947
movl -0x9c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9c(%rbp)
jmp 0x2b462
leaq -0x90(%rbp), %rdi
callq 0xe8c0
leaq -0x50(%rbp), %rdi
callq 0xe8c0
leaq -0x38(%rbp), %rdi
callq 0xe8c0
addq $0x200, %rsp            # imm = 0x200
popq %rbp
retq
leaq -0x50(%rbp), %rdi
callq 0xe8c0
leaq -0x38(%rbp), %rdi
callq 0xe8c0
movq -0x58(%rbp), %rdi
callq 0x57a0
nopl (%rax)