// File: kobanium[P]Ray/src/learn/FactorizationMachines.cpp
// Function: ProcessPosition(game_info_t*, int, int, int)
static void
ProcessPosition( game_info_t *game, const int expertMove, const int color, const int thread_id )
{
  std::map<int, btfm_t*> featureMap;
  std::vector<btfm_t*> featureList[BOARD_MAX];
  const double alpha = learning_rate;
  const double alphaV = alpha;

  CorrectAllFeatures(game, color, featureList, featureMap);

  std::vector<double> scoreList;
  double totalScore = 0.0, gammaTable[BOARD_MAX], thetaTable[BOARD_MAX];


  // 1次の項と2次の項のスコアを求める
  for (int p = 0; p < PURE_BOARD_MAX; p++) {
    const int pos = onboard_pos[p];
    if (!IsLegal(game, pos, color)) {
      continue;
    }

    std::vector<btfm_t*>& feature = featureList[pos];
    const int size = feature.size();

    // 1次のスコアの導出
    double score = CalculateFirstTerm(feature, size);

    gammaTable[pos] = score;

    // 2次のスコアの導出
    if (has_interaction) {
      double theta = 1.0;
      for (int i = 0; i < size - 1; i++) {
        for (int j = i + 1; j < size; j++) {
          theta *= CalculateSecondTerm(feature, i, j);
        }
      }
      thetaTable[pos] = theta;
      score += theta;
    }

    totalScore += score;
    scoreList.push_back(score);
  }

  // パス
  {
    std::vector<btfm_t*>& feature = featureList[PASS];
    const int size = feature.size();

    // 1次のスコアの導出
    double score = CalculateFirstTerm(feature, size);

    gammaTable[PASS] = score;

    // 2次のスコアの導出
    if (has_interaction && size > 1) {
      double theta = 1.0;
      for (int i = 0; i < size - 1; i++) {
        for (int j = i + 1; j < size; j++) {
          theta *= CalculateSecondTerm(feature, i, j);
        }
      }
      thetaTable[PASS] = theta;
      score += theta;
    } else {
      thetaTable[PASS] = 0;
    }

    totalScore += score;
    scoreList.push_back(score);
  }

  double expertScore = gammaTable[expertMove];
  if (has_interaction) {
    expertScore += thetaTable[expertMove];
  }

  const double invTotal = 1.0 / totalScore;
  const double invTotalN = 1.0 / (totalScore * static_cast<double>(FM_DIMENSION));

  // 全ての着手に共通する項の計算
  for (int p = 0; p < PURE_BOARD_MAX; p++) {
    const int pos = onboard_pos[p];
    if (!IsLegal(game, pos, color)) {
      continue;
    }

    std::vector<btfm_t*>& feature = featureList[pos];
    const int size = feature.size();

    // 1次の項の勾配
    for (int i = 0; i < size; i++) {
      feature[i]->grad_w[thread_id] -= gammaTable[pos] * invTotal / feature[i]->w;
    }
    // 2次の項の勾配
    if (has_interaction) {
      const double thetaP = thetaTable[pos];
      for (int i = 0; i < size; i++) {
        for (int k = 0; k < FM_DIMENSION; k++) {
          double sum = 0;
          for (int j = 0; j < size; j++) {
            if (i == j) continue;
            sum += feature[j]->v[k] / CalculateSecondTerm(feature, i, j);
          }
          feature[i]->grad_v[thread_id][k] -= thetaP * sum * invTotalN;
        }
      }
    }
  }

  // パス
  {
    std::vector<btfm_t*>& feature = featureList[PASS];
    const int size = feature.size();

    // 1次の項の勾配
    for (int i = 0; i < size; i++) {
      feature[i]->grad_w[thread_id] -= gammaTable[PASS] * invTotal / feature[i]->w;
    }
    // 2次の項の勾配
    if (has_interaction) {
      const double thetaP = thetaTable[PASS];
      for (int i = 0; i < size; i++) {
        for (int k = 0; k < FM_DIMENSION; k++) {
          double sum = 0;
          for (int j = 0; j < size; j++) {
            if (i == j) continue;
            sum += feature[j]->v[k] / CalculateSecondTerm(feature, i, j);
          }
          feature[i]->grad_v[thread_id][k] -= thetaP * sum * invTotalN;
        }
      }
    }
  }

  // 教師データの着手のみにある項の計算
  {
    std::vector<btfm_t*>& feature = featureList[expertMove];
    const int size = feature.size();
    const double thetaP = thetaTable[expertMove];
    const double invExpertScoreN = 1 / (expertScore * FM_DIMENSION);
    const double deltaT = gammaTable[expertMove] / expertScore;

    for (int i = 0; i < size; i++) {
      feature[i]->grad_w[thread_id] += deltaT / feature[i]->w;
    }

    if (has_interaction && size > 1) {
      for (int i = 0; i < size; i++) {
        for (int k = 0; k < FM_DIMENSION; k++) {
          double sum = 0;
          for (int j = 0; j < size; j++) {
            if (i == j) continue;
            sum += feature[j]->v[k] / CalculateSecondTerm(feature, i, j);
          }
          feature[i]->grad_v[thread_id][k] += thetaP * sum * invExpertScoreN;
        }
      }
    }
  }

  for (auto &x : featureMap) {
    btfm_t *feature = x.second;
    mutex_terms[feature->id].lock();
    UpdateFirstTermAdam(feature, alpha, lambda, minW, thread_id);
    if (has_interaction) {
      UpdateSecondTermAdam(feature, alphaV, lambdaV, minV, thread_id);
    }
    mutex_terms[feature->id].unlock();
  }

  std::sort(scoreList.begin(), scoreList.end(), std::greater<double>());

  for (unsigned int i = 0; i < scoreList.size(); i++) {
    if (expertScore >= scoreList[i]) {
      prediction[i].fetch_add(1);
      break;
    }
  }

  const double p = expertScore * invTotal;
  if (p > 0) {
    mutex_likelihood.lock();
    likelihood += std::log(p);
    mutex_likelihood.unlock();
  } else {
    std::cerr << "Error likelihood : " << p << std::endl;
  }

  counter.fetch_add(1);
  all_moves.fetch_add(1);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x8720, %rsp           # imm = 0x8720
movq %rdi, -0x50(%rbp)
movl %esi, -0x54(%rbp)
movl %edx, -0x58(%rbp)
movl %ecx, -0x5c(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x66c90
leaq -0x4f70(%rbp), %rax
movq %rax, %rcx
addq $0x4ed8, %rcx           # imm = 0x4ED8
movq %rcx, -0x85c8(%rbp)
movq %rax, -0x85c0(%rbp)
movq -0x85c0(%rbp), %rdi
movq %rdi, -0x85d0(%rbp)
callq 0x66cb0
movq -0x85d0(%rbp), %rax
movq -0x85c8(%rbp), %rcx
addq $0x18, %rax
cmpq %rcx, %rax
movq %rax, -0x85c0(%rbp)
jne 0x5cfc3
movsd 0x8a9ac(%rip), %xmm0    # 0xe79a8
movsd %xmm0, -0x4f78(%rbp)
movsd -0x4f78(%rbp), %xmm0
movsd %xmm0, -0x4f80(%rbp)
movq -0x50(%rbp), %rdi
movl -0x58(%rbp), %esi
leaq -0x4f70(%rbp), %rdx
leaq -0x90(%rbp), %rcx
callq 0x5e230
jmp 0x5d030
leaq -0x4fa8(%rbp), %rdi
callq 0x66cd0
xorps %xmm0, %xmm0
movsd %xmm0, -0x4fb0(%rbp)
movl $0x0, -0x8454(%rbp)
cmpl $0x169, -0x8454(%rbp)   # imm = 0x169
jge 0x5d273
movslq -0x8454(%rbp), %rcx
leaq 0x1ab75801(%rip), %rax  # 0x1abd2870
movl (%rax,%rcx,4), %eax
movl %eax, -0x8458(%rbp)
movq -0x50(%rbp), %rdi
movl -0x8458(%rbp), %esi
movl -0x58(%rbp), %edx
callq 0x9d0b0
movb %al, -0x85d1(%rbp)
jmp 0x5d092
movb -0x85d1(%rbp), %al
testb $0x1, %al
jne 0x5d0dd
jmp 0x5d09e
jmp 0x5d25f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x4f88(%rbp)
movl %eax, -0x4f8c(%rbp)
jmp 0x5e1c1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x4f88(%rbp)
movl %eax, -0x4f8c(%rbp)
leaq -0x4fa8(%rbp), %rdi
callq 0x66fb0
jmp 0x5e1c1
movslq -0x8458(%rbp), %rax
leaq (%rax,%rax,2), %rax
leaq -0x4f70(%rbp,%rax,8), %rax
movq %rax, -0x8460(%rbp)
movq -0x8460(%rbp), %rdi
callq 0x66cf0
movl %eax, -0x8464(%rbp)
movq -0x8460(%rbp), %rdi
movl -0x8464(%rbp), %esi
callq 0x5eef0
movsd %xmm0, -0x85e0(%rbp)
jmp 0x5d125
movsd -0x85e0(%rbp), %xmm0
movsd %xmm0, -0x8470(%rbp)
movsd -0x8470(%rbp), %xmm0
movslq -0x8458(%rbp), %rax
movsd %xmm0, -0x6a00(%rbp,%rax,8)
movsd 0x4eeb3(%rip), %xmm0    # 0xac008
movsd %xmm0, -0x8478(%rbp)
movl $0x0, -0x847c(%rbp)
movl -0x847c(%rbp), %eax
movl -0x8464(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x5d1f8
movl -0x847c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8480(%rbp)
movl -0x8480(%rbp), %eax
cmpl -0x8464(%rbp), %eax
jge 0x5d1e2
movq -0x8460(%rbp), %rdi
movl -0x847c(%rbp), %esi
movl -0x8480(%rbp), %edx
callq 0x5ef50
movsd %xmm0, -0x85e8(%rbp)
jmp 0x5d1b9
movsd -0x85e8(%rbp), %xmm0
mulsd -0x8478(%rbp), %xmm0
movsd %xmm0, -0x8478(%rbp)
movl -0x8480(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8480(%rbp)
jmp 0x5d189
jmp 0x5d1e4
movl -0x847c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x847c(%rbp)
jmp 0x5d167
movsd -0x8478(%rbp), %xmm0
movslq -0x8458(%rbp), %rax
movsd %xmm0, -0x8450(%rbp,%rax,8)
movsd -0x8478(%rbp), %xmm1
movsd -0x8470(%rbp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x8470(%rbp)
movsd -0x8470(%rbp), %xmm1
movsd -0x4fb0(%rbp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x4fb0(%rbp)
leaq -0x4fa8(%rbp), %rdi
leaq -0x8470(%rbp), %rsi
callq 0x66d10
jmp 0x5d25d
jmp 0x5d25f
movl -0x8454(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8454(%rbp)
jmp 0x5d051
leaq -0x4f70(%rbp), %rax
movq %rax, -0x8488(%rbp)
movq -0x8488(%rbp), %rdi
callq 0x66cf0
movl %eax, -0x848c(%rbp)
movq -0x8488(%rbp), %rdi
movl -0x848c(%rbp), %esi
callq 0x5eef0
movsd %xmm0, -0x85f0(%rbp)
jmp 0x5d2af
movsd -0x85f0(%rbp), %xmm0
movsd %xmm0, -0x8498(%rbp)
movsd -0x8498(%rbp), %xmm0
movsd %xmm0, -0x6a00(%rbp)
cmpl $0x1, -0x848c(%rbp)
jle 0x5d3b1
movsd 0x4ed24(%rip), %xmm0    # 0xac008
movsd %xmm0, -0x84a0(%rbp)
movl $0x0, -0x84a4(%rbp)
movl -0x84a4(%rbp), %eax
movl -0x848c(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x5d387
movl -0x84a4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84a8(%rbp)
movl -0x84a8(%rbp), %eax
cmpl -0x848c(%rbp), %eax
jge 0x5d371
movq -0x8488(%rbp), %rdi
movl -0x84a4(%rbp), %esi
movl -0x84a8(%rbp), %edx
callq 0x5ef50
movsd %xmm0, -0x85f8(%rbp)
jmp 0x5d348
movsd -0x85f8(%rbp), %xmm0
mulsd -0x84a0(%rbp), %xmm0
movsd %xmm0, -0x84a0(%rbp)
movl -0x84a8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84a8(%rbp)
jmp 0x5d318
jmp 0x5d373
movl -0x84a4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84a4(%rbp)
jmp 0x5d2f6
movsd -0x84a0(%rbp), %xmm0
movsd %xmm0, -0x8450(%rbp)
movsd -0x84a0(%rbp), %xmm0
addsd -0x8498(%rbp), %xmm0
movsd %xmm0, -0x8498(%rbp)
jmp 0x5d3bc
xorps %xmm0, %xmm0
movsd %xmm0, -0x8450(%rbp)
movsd -0x8498(%rbp), %xmm1
movsd -0x4fb0(%rbp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x4fb0(%rbp)
leaq -0x4fa8(%rbp), %rdi
leaq -0x8498(%rbp), %rsi
callq 0x66d10
jmp 0x5d3ed
movslq -0x54(%rbp), %rax
movsd -0x6a00(%rbp,%rax,8), %xmm0
movsd %xmm0, -0x84b0(%rbp)
movslq -0x54(%rbp), %rax
movsd -0x8450(%rbp,%rax,8), %xmm0
addsd -0x84b0(%rbp), %xmm0
movsd %xmm0, -0x84b0(%rbp)
movsd 0x4ebe1(%rip), %xmm0    # 0xac008
divsd -0x4fb0(%rbp), %xmm0
movsd %xmm0, -0x84b8(%rbp)
movsd 0x50ae9(%rip), %xmm1    # 0xadf28
mulsd -0x4fb0(%rbp), %xmm1
movsd 0x4ebb9(%rip), %xmm0    # 0xac008
divsd %xmm1, %xmm0
movsd %xmm0, -0x84c0(%rbp)
movl $0x0, -0x84c4(%rbp)
cmpl $0x169, -0x84c4(%rbp)   # imm = 0x169
jge 0x5d765
movslq -0x84c4(%rbp), %rcx
leaq 0x1ab753ed(%rip), %rax  # 0x1abd2870
movl (%rax,%rcx,4), %eax
movl %eax, -0x84c8(%rbp)
movq -0x50(%rbp), %rdi
movl -0x84c8(%rbp), %esi
movl -0x58(%rbp), %edx
callq 0x9d0b0
movb %al, -0x85f9(%rbp)
jmp 0x5d4a6
movb -0x85f9(%rbp), %al
testb $0x1, %al
jne 0x5d4b7
jmp 0x5d4b2
jmp 0x5d751
movslq -0x84c8(%rbp), %rcx
leaq -0x4f70(%rbp), %rax
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x84d0(%rbp)
movq -0x84d0(%rbp), %rdi
callq 0x66cf0
movl %eax, -0x84d4(%rbp)
movl $0x0, -0x84d8(%rbp)
movl -0x84d8(%rbp), %eax
cmpl -0x84d4(%rbp), %eax
jge 0x5d591
movslq -0x84c8(%rbp), %rax
movsd -0x6a00(%rbp,%rax,8), %xmm0
mulsd -0x84b8(%rbp), %xmm0
movsd %xmm0, -0x8610(%rbp)
movq -0x84d0(%rbp), %rdi
movslq -0x84d8(%rbp), %rsi
callq 0x66d80
movsd -0x8610(%rbp), %xmm0
movq (%rax), %rax
divsd (%rax), %xmm0
movsd %xmm0, -0x8608(%rbp)
movq -0x84d0(%rbp), %rdi
movslq -0x84d8(%rbp), %rsi
callq 0x66d80
movsd -0x8608(%rbp), %xmm1
movq (%rax), %rax
movslq -0x5c(%rbp), %rcx
movsd 0x30(%rax,%rcx,8), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x30(%rax,%rcx,8)
movl -0x84d8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84d8(%rbp)
jmp 0x5d4ef
movslq -0x84c8(%rbp), %rax
movsd -0x8450(%rbp,%rax,8), %xmm0
movsd %xmm0, -0x84e0(%rbp)
movl $0x0, -0x84e4(%rbp)
movl -0x84e4(%rbp), %eax
cmpl -0x84d4(%rbp), %eax
jge 0x5d74f
movl $0x0, -0x84e8(%rbp)
cmpl $0x5, -0x84e8(%rbp)
jge 0x5d739
xorps %xmm0, %xmm0
movsd %xmm0, -0x84f0(%rbp)
movl $0x0, -0x84f4(%rbp)
movl -0x84f4(%rbp), %eax
cmpl -0x84d4(%rbp), %eax
jge 0x5d698
movl -0x84e4(%rbp), %eax
cmpl -0x84f4(%rbp), %eax
jne 0x5d613
jmp 0x5d684
movq -0x84d0(%rbp), %rdi
movslq -0x84f4(%rbp), %rsi
callq 0x66d80
movq (%rax), %rax
movslq -0x84e8(%rbp), %rcx
movsd 0x8(%rax,%rcx,8), %xmm0
movsd %xmm0, -0x8620(%rbp)
movq -0x84d0(%rbp), %rdi
movl -0x84e4(%rbp), %esi
movl -0x84f4(%rbp), %edx
callq 0x5ef50
movsd %xmm0, -0x8618(%rbp)
jmp 0x5d660
movsd -0x8618(%rbp), %xmm1
movsd -0x8620(%rbp), %xmm0
divsd %xmm1, %xmm0
addsd -0x84f0(%rbp), %xmm0
movsd %xmm0, -0x84f0(%rbp)
movl -0x84f4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84f4(%rbp)
jmp 0x5d5f1
movsd -0x84e0(%rbp), %xmm0
mulsd -0x84f0(%rbp), %xmm0
movsd %xmm0, -0x8630(%rbp)
movsd -0x84c0(%rbp), %xmm0
movsd %xmm0, -0x8628(%rbp)
movq -0x84d0(%rbp), %rdi
movslq -0x84e4(%rbp), %rsi
callq 0x66d80
movsd -0x8630(%rbp), %xmm0
movsd -0x8628(%rbp), %xmm2
movq (%rax), %rax
addq $0x70, %rax
movslq -0x5c(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movslq -0x84e8(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
movq %xmm0, %rdx
movabsq $-0x8000000000000000, %rsi # imm = 0x8000000000000000
xorq %rsi, %rdx
movq %rdx, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x84e8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84e8(%rbp)
jmp 0x5d5cf
jmp 0x5d73b
movl -0x84e4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84e4(%rbp)
jmp 0x5d5b3
jmp 0x5d751
movl -0x84c4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84c4(%rbp)
jmp 0x5d465
leaq -0x4f70(%rbp), %rax
movq %rax, -0x8500(%rbp)
movq -0x8500(%rbp), %rdi
callq 0x66cf0
movl %eax, -0x8504(%rbp)
movl $0x0, -0x8508(%rbp)
movl -0x8508(%rbp), %eax
cmpl -0x8504(%rbp), %eax
jge 0x5d829
movsd -0x6a00(%rbp), %xmm0
mulsd -0x84b8(%rbp), %xmm0
movsd %xmm0, -0x8640(%rbp)
movq -0x8500(%rbp), %rdi
movslq -0x8508(%rbp), %rsi
callq 0x66d80
movsd -0x8640(%rbp), %xmm0
movq (%rax), %rax
divsd (%rax), %xmm0
movsd %xmm0, -0x8638(%rbp)
movq -0x8500(%rbp), %rdi
movslq -0x8508(%rbp), %rsi
callq 0x66d80
movsd -0x8638(%rbp), %xmm1
movq (%rax), %rax
movslq -0x5c(%rbp), %rcx
movsd 0x30(%rax,%rcx,8), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x30(%rax,%rcx,8)
movl -0x8508(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8508(%rbp)
jmp 0x5d78f
movsd -0x8450(%rbp), %xmm0
movsd %xmm0, -0x8510(%rbp)
movl $0x0, -0x8514(%rbp)
movl -0x8514(%rbp), %eax
cmpl -0x8504(%rbp), %eax
jge 0x5d9df
movl $0x0, -0x8518(%rbp)
cmpl $0x5, -0x8518(%rbp)
jge 0x5d9c9
xorps %xmm0, %xmm0
movsd %xmm0, -0x8520(%rbp)
movl $0x0, -0x8524(%rbp)
movl -0x8524(%rbp), %eax
cmpl -0x8504(%rbp), %eax
jge 0x5d928
movl -0x8514(%rbp), %eax
cmpl -0x8524(%rbp), %eax
jne 0x5d8a3
jmp 0x5d914
movq -0x8500(%rbp), %rdi
movslq -0x8524(%rbp), %rsi
callq 0x66d80
movq (%rax), %rax
movslq -0x8518(%rbp), %rcx
movsd 0x8(%rax,%rcx,8), %xmm0
movsd %xmm0, -0x8650(%rbp)
movq -0x8500(%rbp), %rdi
movl -0x8514(%rbp), %esi
movl -0x8524(%rbp), %edx
callq 0x5ef50
movsd %xmm0, -0x8648(%rbp)
jmp 0x5d8f0
movsd -0x8648(%rbp), %xmm1
movsd -0x8650(%rbp), %xmm0
divsd %xmm1, %xmm0
addsd -0x8520(%rbp), %xmm0
movsd %xmm0, -0x8520(%rbp)
movl -0x8524(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8524(%rbp)
jmp 0x5d881
movsd -0x8510(%rbp), %xmm0
mulsd -0x8520(%rbp), %xmm0
movsd %xmm0, -0x8660(%rbp)
movsd -0x84c0(%rbp), %xmm0
movsd %xmm0, -0x8658(%rbp)
movq -0x8500(%rbp), %rdi
movslq -0x8514(%rbp), %rsi
callq 0x66d80
movsd -0x8660(%rbp), %xmm0
movsd -0x8658(%rbp), %xmm2
movq (%rax), %rax
addq $0x70, %rax
movslq -0x5c(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movslq -0x8518(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
movq %xmm0, %rdx
movabsq $-0x8000000000000000, %rsi # imm = 0x8000000000000000
xorq %rsi, %rdx
movq %rdx, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x8518(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8518(%rbp)
jmp 0x5d85f
jmp 0x5d9cb
movl -0x8514(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8514(%rbp)
jmp 0x5d843
movslq -0x54(%rbp), %rcx
leaq -0x4f70(%rbp), %rax
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x8530(%rbp)
movq -0x8530(%rbp), %rdi
callq 0x66cf0
movl %eax, -0x8534(%rbp)
movslq -0x54(%rbp), %rax
movsd -0x8450(%rbp,%rax,8), %xmm0
movsd %xmm0, -0x8540(%rbp)
movsd 0x50501(%rip), %xmm1    # 0xadf28
mulsd -0x84b0(%rbp), %xmm1
movsd 0x4e5d1(%rip), %xmm0    # 0xac008
divsd %xmm1, %xmm0
movsd %xmm0, -0x8548(%rbp)
movslq -0x54(%rbp), %rax
movsd -0x6a00(%rbp,%rax,8), %xmm0
divsd -0x84b0(%rbp), %xmm0
movsd %xmm0, -0x8550(%rbp)
movl $0x0, -0x8554(%rbp)
movl -0x8554(%rbp), %eax
cmpl -0x8534(%rbp), %eax
jge 0x5daf4
movsd -0x8550(%rbp), %xmm0
movsd %xmm0, -0x8670(%rbp)
movq -0x8530(%rbp), %rdi
movslq -0x8554(%rbp), %rsi
callq 0x66d80
movsd -0x8670(%rbp), %xmm0
movq (%rax), %rax
divsd (%rax), %xmm0
movsd %xmm0, -0x8668(%rbp)
movq -0x8530(%rbp), %rdi
movslq -0x8554(%rbp), %rsi
callq 0x66d80
movsd -0x8668(%rbp), %xmm0
movq (%rax), %rax
movslq -0x5c(%rbp), %rcx
addsd 0x30(%rax,%rcx,8), %xmm0
movsd %xmm0, 0x30(%rax,%rcx,8)
movl -0x8554(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8554(%rbp)
jmp 0x5da6a
cmpl $0x1, -0x8534(%rbp)
jle 0x5dc92
movl $0x0, -0x8558(%rbp)
movl -0x8558(%rbp), %eax
cmpl -0x8534(%rbp), %eax
jge 0x5dc90
movl $0x0, -0x855c(%rbp)
cmpl $0x5, -0x855c(%rbp)
jge 0x5dc7a
xorps %xmm0, %xmm0
movsd %xmm0, -0x8568(%rbp)
movl $0x0, -0x856c(%rbp)
movl -0x856c(%rbp), %eax
cmpl -0x8534(%rbp), %eax
jge 0x5dbf0
movl -0x8558(%rbp), %eax
cmpl -0x856c(%rbp), %eax
jne 0x5db6b
jmp 0x5dbdc
movq -0x8530(%rbp), %rdi
movslq -0x856c(%rbp), %rsi
callq 0x66d80
movq (%rax), %rax
movslq -0x855c(%rbp), %rcx
movsd 0x8(%rax,%rcx,8), %xmm0
movsd %xmm0, -0x8680(%rbp)
movq -0x8530(%rbp), %rdi
movl -0x8558(%rbp), %esi
movl -0x856c(%rbp), %edx
callq 0x5ef50
movsd %xmm0, -0x8678(%rbp)
jmp 0x5dbb8
movsd -0x8678(%rbp), %xmm1
movsd -0x8680(%rbp), %xmm0
divsd %xmm1, %xmm0
addsd -0x8568(%rbp), %xmm0
movsd %xmm0, -0x8568(%rbp)
movl -0x856c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x856c(%rbp)
jmp 0x5db49
movsd -0x8540(%rbp), %xmm0
mulsd -0x8568(%rbp), %xmm0
movsd %xmm0, -0x8690(%rbp)
movsd -0x8548(%rbp), %xmm0
movsd %xmm0, -0x8688(%rbp)
movq -0x8530(%rbp), %rdi
movslq -0x8558(%rbp), %rsi
callq 0x66d80
movsd -0x8690(%rbp), %xmm0
movsd -0x8688(%rbp), %xmm2
movq (%rax), %rax
addq $0x70, %rax
movslq -0x5c(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movslq -0x855c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x855c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x855c(%rbp)
jmp 0x5db27
jmp 0x5dc7c
movl -0x8558(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8558(%rbp)
jmp 0x5db0b
jmp 0x5dc92
leaq -0x90(%rbp), %rax
movq %rax, -0x8578(%rbp)
movq -0x8578(%rbp), %rdi
callq 0x66da0
movq %rax, -0x8580(%rbp)
movq -0x8578(%rbp), %rdi
callq 0x66dd0
movq %rax, -0x8588(%rbp)
leaq -0x8580(%rbp), %rdi
leaq -0x8588(%rbp), %rsi
callq 0x66e00
testb $0x1, %al
jne 0x5dce2
jmp 0x5ddb4
leaq -0x8580(%rbp), %rdi
callq 0x66e30
movq %rax, -0x8590(%rbp)
movq -0x8590(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x8598(%rbp)
movq 0x8b9a2(%rip), %rax     # 0xe96b0
movq -0x8598(%rbp), %rcx
movslq 0x210(%rcx), %rcx
leaq (%rcx,%rcx,4), %rcx
leaq (%rax,%rcx,8), %rdi
callq 0x66e50
jmp 0x5dd2b
movq -0x8598(%rbp), %rdi
movsd -0x4f78(%rbp), %xmm0
movl -0x5c(%rbp), %esi
movsd 0x501c3(%rip), %xmm1    # 0xadf08
movsd 0x501e3(%rip), %xmm2    # 0xadf30
callq 0x5eff0
jmp 0x5dd54
movq -0x8598(%rbp), %rdi
movsd -0x4f80(%rbp), %xmm0
movl -0x5c(%rbp), %esi
movsd 0x501ca(%rip), %xmm1    # 0xadf38
movsd 0x501ba(%rip), %xmm2    # 0xadf30
callq 0x5f200
jmp 0x5dd7d
movq 0x8b92c(%rip), %rax     # 0xe96b0
movq -0x8598(%rbp), %rcx
movslq 0x210(%rcx), %rcx
leaq (%rcx,%rcx,4), %rcx
leaq (%rax,%rcx,8), %rdi
callq 0x66e80
jmp 0x5dda1
jmp 0x5dda3
leaq -0x8580(%rbp), %rdi
callq 0x66ea0
jmp 0x5dcc6
leaq -0x4fa8(%rbp), %rdi
movq %rdi, -0x8698(%rbp)
callq 0x66f10
movq -0x8698(%rbp), %rdi
movq %rax, -0x85a0(%rbp)
callq 0x66f40
movq %rax, -0x85a8(%rbp)
movq -0x85a0(%rbp), %rdi
movq -0x85a8(%rbp), %rsi
callq 0x66ed0
jmp 0x5ddf6
movl $0x0, -0x85b0(%rbp)
movl -0x85b0(%rbp), %eax
movq %rax, -0x86a0(%rbp)
leaq -0x4fa8(%rbp), %rdi
callq 0x66f70
movq %rax, %rcx
movq -0x86a0(%rbp), %rax
cmpq %rcx, %rax
jae 0x5df37
movsd -0x84b0(%rbp), %xmm0
movsd %xmm0, -0x86a8(%rbp)
movl -0x85b0(%rbp), %eax
movl %eax, %esi
leaq -0x4fa8(%rbp), %rdi
callq 0x66f90
movsd -0x86a8(%rbp), %xmm0
ucomisd (%rax), %xmm0
jb 0x5df21
movl -0x85b0(%rbp), %eax
movl %eax, %ecx
leaq 0x8b84f(%rip), %rax     # 0xe96c0
leaq (%rax,%rcx,4), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0xc(%rbp)
movl $0x5, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x86b8(%rbp)
movl -0x10(%rbp), %eax
movl -0xc(%rbp), %ecx
movl %ecx, -0x14(%rbp)
decl %eax
movl %eax, %ecx
movq %rcx, -0x86b0(%rbp)
subl $0x4, %eax
ja 0x5dec2
movq -0x86b0(%rbp), %rax
leaq 0x500e7(%rip), %rcx     # 0xadfa0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x86b8(%rbp), %rcx
movl -0x14(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x18(%rbp)
jmp 0x5df1f
movq -0x86b8(%rbp), %rcx
movl -0x14(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x18(%rbp)
jmp 0x5df1f
movq -0x86b8(%rbp), %rcx
movl -0x14(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x18(%rbp)
jmp 0x5df1f
movq -0x86b8(%rbp), %rcx
movl -0x14(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x18(%rbp)
jmp 0x5df1f
movq -0x86b8(%rbp), %rcx
movl -0x14(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x18(%rbp)
jmp 0x5df37
jmp 0x5df23
movl -0x85b0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x85b0(%rbp)
jmp 0x5de00
movsd -0x84b0(%rbp), %xmm0
mulsd -0x84b8(%rbp), %xmm0
movsd %xmm0, -0x85b8(%rbp)
movsd -0x85b8(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x5dfa2
leaq 0x8bd09(%rip), %rdi     # 0xe9c70
callq 0x66e50
jmp 0x5df6e
movsd -0x85b8(%rbp), %xmm0
callq 0x7420
movaps %xmm0, %xmm1
movsd 0x8bce2(%rip), %xmm0    # 0xe9c68
addsd %xmm1, %xmm0
movsd %xmm0, 0x8bcd6(%rip)    # 0xe9c68
leaq 0x8bcd7(%rip), %rdi     # 0xe9c70
callq 0x66e80
jmp 0x5dfa0
jmp 0x5dff2
movq 0x89047(%rip), %rdi     # 0xe6ff0
leaq 0x50118(%rip), %rsi     # 0xae0c8
callq 0x7530
movq %rax, -0x86c0(%rbp)
jmp 0x5dfbe
movq -0x86c0(%rbp), %rdi
movsd -0x85b8(%rbp), %xmm0
callq 0x7a60
movq %rax, -0x86c8(%rbp)
jmp 0x5dfdb
movq -0x86c8(%rbp), %rdi
movq 0x88f7f(%rip), %rsi     # 0xe6f68
callq 0x75b0
jmp 0x5dff0
jmp 0x5dff2
leaq 0x8b6b3(%rip), %rax     # 0xe96ac
movq %rax, -0x20(%rbp)
movl $0x1, -0x24(%rbp)
movl $0x5, -0x28(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x86d8(%rbp)
movl -0x28(%rbp), %eax
movl -0x24(%rbp), %ecx
movl %ecx, -0x2c(%rbp)
decl %eax
movl %eax, %ecx
movq %rcx, -0x86d0(%rbp)
subl $0x4, %eax
ja 0x5e046
movq -0x86d0(%rbp), %rax
leaq 0x4ff77(%rip), %rcx     # 0xadfb4
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x86d8(%rbp), %rcx
movl -0x2c(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x30(%rbp)
jmp 0x5e0a3
movq -0x86d8(%rbp), %rcx
movl -0x2c(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x30(%rbp)
jmp 0x5e0a3
movq -0x86d8(%rbp), %rcx
movl -0x2c(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x30(%rbp)
jmp 0x5e0a3
movq -0x86d8(%rbp), %rcx
movl -0x2c(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x30(%rbp)
jmp 0x5e0a3
movq -0x86d8(%rbp), %rcx
movl -0x2c(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x30(%rbp)
leaq 0x8b5fe(%rip), %rax     # 0xe96a8
movq %rax, -0x38(%rbp)
movl $0x1, -0x3c(%rbp)
movl $0x5, -0x40(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x86e8(%rbp)
movl -0x40(%rbp), %eax
movl -0x3c(%rbp), %ecx
movl %ecx, -0x44(%rbp)
decl %eax
movl %eax, %ecx
movq %rcx, -0x86e0(%rbp)
subl $0x4, %eax
ja 0x5e0f7
movq -0x86e0(%rbp), %rax
leaq 0x4feda(%rip), %rcx     # 0xadfc8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x86e8(%rbp), %rcx
movl -0x44(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x48(%rbp)
jmp 0x5e154
movq -0x86e8(%rbp), %rcx
movl -0x44(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x48(%rbp)
jmp 0x5e154
movq -0x86e8(%rbp), %rcx
movl -0x44(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x48(%rbp)
jmp 0x5e154
movq -0x86e8(%rbp), %rcx
movl -0x44(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x48(%rbp)
jmp 0x5e154
movq -0x86e8(%rbp), %rcx
movl -0x44(%rbp), %eax
lock
xaddl %eax, (%rcx)
movl %eax, -0x48(%rbp)
leaq -0x4fa8(%rbp), %rdi
callq 0x66fb0
leaq -0x4f70(%rbp), %rax
movq %rax, -0x86f8(%rbp)
addq $0x4ed8, %rax           # imm = 0x4ED8
movq %rax, -0x86f0(%rbp)
movq -0x86f0(%rbp), %rdi
addq $-0x18, %rdi
movq %rdi, -0x8700(%rbp)
callq 0x67010
movq -0x86f8(%rbp), %rcx
movq -0x8700(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x86f0(%rbp)
jne 0x5e17b
leaq -0x90(%rbp), %rdi
callq 0x67070
addq $0x8720, %rsp           # imm = 0x8720
popq %rbp
retq
leaq -0x4f70(%rbp), %rax
movq %rax, -0x8710(%rbp)
addq $0x4ed8, %rax           # imm = 0x4ED8
movq %rax, -0x8708(%rbp)
movq -0x8708(%rbp), %rdi
addq $-0x18, %rdi
movq %rdi, -0x8718(%rbp)
callq 0x67010
movq -0x8710(%rbp), %rcx
movq -0x8718(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x8708(%rbp)
jne 0x5e1dc
leaq -0x90(%rbp), %rdi
callq 0x67070
movq -0x4f88(%rbp), %rdi
callq 0x79b0
nopw %cs:(%rax,%rax)