// File: /workspace/github_cpp_makefile_star2_O3/tbjohns[P]BlitzL1/src/solver.cpp
// Function: BlitzL1::Solver::run_prox_newton_iteration(double*, double&, double, BlitzL1::Loss const*, BlitzL1::Dataset const*)
value_t Solver::run_prox_newton_iteration(value_t *x,
                                            value_t &intercept,
                                            value_t lambda,
                                            const Loss *loss_function,
                                            const Dataset *data)
  {
    // Runs one iteration of subproblem solver
    // Returns theta_scale, which is the largest scaler value <= 1
    // for which scaler*theta is feasible for the subproblem

    // Initialize iteration:
    size_t n = data->get_n();
    vector<value_t> Delta_x(working_set_size, 0.0);
    vector<value_t> A_Delta_x(n, 0.0);
    value_t Delta_intercept = 0.0;

    // Permutation vector for shuffling indices:
    vector<size_t> rand_permutation;
    rand_permutation.reserve(working_set_size);
    for (size_t ind = 0; ind < working_set_size; ++ind)
      rand_permutation.push_back(ind);

    // Set up hessian values:
    vector<value_t> H;
    loss_function->compute_H(H, theta, Ax, data);
    vector<value_t> hess_cache(working_set_size, 0.0);
    for (size_t ind = 0; ind < working_set_size; ++ind)
    {
      size_t j = prioritized_features[ind];
      hess_cache[ind] = data->get_column(j)->h_norm_sq(H);
    }

    // Cache values for updating intercept:
    value_t sum_theta = sum_vector(theta);
    value_t sum_H = sum_vector(H);

    // Finish set up for approximate newton step:
    value_t prox_newton_epsilon = 0.0;
    int max_cd_itr = MAX_PROX_NEWTON_CD_ITR;
    if (first_prox_newton_iteration)
    {
      max_cd_itr = MIN_PROX_NEWTON_CD_ITR;
      first_prox_newton_iteration = false;

      // Set up gradient values:
      prox_newton_grad_cache.resize(working_set_size);
      for (size_t ind = 0; ind < working_set_size; ++ind)
      {
        size_t j = prioritized_features[ind];
        prox_newton_grad_cache[ind] = data->get_column(j)->inner_product(theta);
      }
    }
    else
    {
      prox_newton_epsilon = PROX_NEWTON_EPSILON_RATIO * prox_newton_grad_diff;
    }

    // std::random_device rd;
    std::mt19937 g(0);

    // Approximately solve for newton direction:
    for (int cd_itr = 0; cd_itr < max_cd_itr; ++cd_itr)
    {

      // Shuffle indices:
      shuffle(rand_permutation.begin(), rand_permutation.end(), g);
      for (size_t rp_ind = 0; rp_ind < working_set_size; ++rp_ind)
      {
        size_t new_index = rand_permutation[rp_ind];
        swap(prioritized_features[rp_ind], prioritized_features[new_index]);
        swap(Delta_x[rp_ind], Delta_x[new_index]);
        swap(prox_newton_grad_cache[rp_ind], prox_newton_grad_cache[new_index]);
        swap(hess_cache[rp_ind], hess_cache[new_index]);
      }

      // Compute newton direction using coordinate descent:
      value_t sum_sq_hess_diff = 0.0;
      for (size_t ind = 0; ind < working_set_size; ++ind)
      {
        size_t j = prioritized_features[ind];
        const Column *col = data->get_column(j);

        // Compute hessian and gradient for coordinate j:
        value_t hess = hess_cache[ind];
        if (hess <= 0.0)
          continue;

        value_t grad = prox_newton_grad_cache[ind] + col->weighted_inner_product(A_Delta_x, H);

        // Apply coordinate descent update:
        value_t old_value = x[j] + Delta_x[ind];
        value_t proposal = old_value - grad / hess;
        value_t new_value = soft_threshold(proposal, lambda / hess);
        value_t diff = new_value - old_value;

        if (diff == 0.0)
          continue;

        Delta_x[ind] = new_value - x[j];
        col->add_multiple(A_Delta_x, diff);
        sum_sq_hess_diff += diff * diff * hess * hess;
      }

      // Update intercept:
      if (use_intercept)
      {
        value_t ip = inner_product(H, A_Delta_x);
        value_t diff = -(ip + sum_theta) / sum_H;
        Delta_intercept += diff;
        add_scaler(A_Delta_x, diff);
      }

      if (sum_sq_hess_diff < prox_newton_epsilon && cd_itr + 1 >= MIN_PROX_NEWTON_CD_ITR)
      {
        break;
      }
    }

    // Apply update with backtracking:
    value_t t = 1.0;
    value_t last_t = 0.0;
    for (int backtrack_itr = 0; backtrack_itr < MAX_BACKTRACK_ITR; ++backtrack_itr)
    {
      value_t diff_t = t - last_t;

      intercept += diff_t * Delta_intercept;
      value_t subgrad_t = 0.0;

      for (size_t ind = 0; ind < working_set_size; ++ind)
      {
        size_t j = prioritized_features[ind];
        x[j] += diff_t * Delta_x[ind];
        if (x[j] < 0)
          subgrad_t -= lambda * Delta_x[ind];
        else if (x[j] > 0)
          subgrad_t += lambda * Delta_x[ind];
        else
          subgrad_t -= lambda * fabs(Delta_x[ind]);
      }
      for (size_t i = 0; i < n; ++i)
      {
        Ax[i] += diff_t * A_Delta_x[i];
      }

      loss_function->compute_dual_points(Ax, theta, aux_dual, data);
      subgrad_t += inner_product(A_Delta_x, theta);

      if (subgrad_t < 0)
      {
        break;
      }
      else
      {
        last_t = t;
        t *= 0.5;
      }
    }

    // Update intercept exactly:
    value_t delta_intercept = update_intercept(intercept, loss_function, data);

    // Cache gradients for next iteration:
    if (t != 1.0)
    {
      for (size_t i = 0; i < A_Delta_x.size(); ++i)
      {
        A_Delta_x[i] = t * A_Delta_x[i] + delta_intercept;
      }
    }
    for (size_t ind = 0; ind < working_set_size; ++ind)
    {
      size_t j = prioritized_features[ind];
      const Column *col = data->get_column(j);
      value_t actual_grad = col->inner_product(theta);
      value_t approximate_grad = prox_newton_grad_cache[ind] + col->weighted_inner_product(A_Delta_x, H);

      prox_newton_grad_cache[ind] = actual_grad;
      value_t diff = actual_grad - approximate_grad;
      prox_newton_grad_diff += diff * diff;
    }

    // Compute theta_scale return value:
    value_t max_grad_working_set = max_abs(prox_newton_grad_cache);
    if (max_grad_working_set > lambda)
      return lambda / max_grad_working_set;
    else
      return 1.0;
  }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x14a8, %rsp           # imm = 0x14A8
movq %rcx, 0x78(%rsp)
movapd %xmm0, 0xf0(%rsp)
movq %rdx, 0xa8(%rsp)
movq %rsi, %r13
movq %rdi, %r14
movq %r8, 0x20(%rsp)
movq 0x18(%r8), %r12
movq 0x98(%rdi), %rsi
xorl %r15d, %r15d
leaq 0x120(%rsp), %rbx
movq %r15, (%rbx)
leaq 0xc0(%rsp), %rdi
leaq 0x48(%rsp), %rcx
movq %rbx, %rdx
callq 0x5530
movq %r15, (%rbx)
leaq 0x48(%rsp), %rdi
leaq 0x120(%rsp), %rdx
leaq 0x60(%rsp), %rcx
movq %r12, 0x118(%rsp)
movq %r12, %rsi
callq 0x5530
xorpd %xmm0, %xmm0
leaq 0x60(%rsp), %rdi
movapd %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
movq 0x98(%r14), %rsi
callq 0x5380
movq $0x0, 0x120(%rsp)
cmpq $0x0, 0x98(%r14)
je 0x75b8
xorl %eax, %eax
leaq 0x60(%rsp), %rbx
leaq 0x120(%rsp), %r15
movq 0x68(%rsp), %rsi
cmpq 0x70(%rsp), %rsi
je 0x7591
movq %rax, (%rsi)
addq $0x8, %rsi
movq %rsi, 0x68(%rsp)
jmp 0x759c
movq %rbx, %rdi
movq %r15, %rdx
callq 0x54c0
movq 0x120(%rsp), %rax
incq %rax
movq %rax, 0x120(%rsp)
cmpq 0x98(%r14), %rax
jb 0x7577
xorpd %xmm0, %xmm0
leaq 0x90(%rsp), %rsi
movapd %xmm0, (%rsi)
movq $0x0, 0x10(%rsi)
leaq 0x18(%r14), %rcx
movq 0x78(%rsp), %rdi
movq (%rdi), %rax
movq %r14, %rdx
movq %rcx, 0xb0(%rsp)
movq 0x20(%rsp), %r8
callq *0x18(%rax)
movq 0x98(%r14), %rsi
leaq 0x120(%rsp), %rdx
movq $0x0, (%rdx)
leaq 0xd8(%rsp), %rdi
leaq 0x2b(%rsp), %rcx
callq 0x5530
cmpq $0x0, 0x98(%r14)
je 0x7666
xorl %r15d, %r15d
leaq 0x90(%rsp), %rbx
movq 0xa0(%r14), %rax
movslq (%rax,%r15,8), %rax
movq 0x20(%rsp), %rcx
movq (%rcx), %rcx
movq (%rcx,%rax,8), %rdi
movq (%rdi), %rax
movq %rbx, %rsi
callq *0x10(%rax)
movq 0xd8(%rsp), %rax
movsd %xmm0, (%rax,%r15,8)
incq %r15
cmpq 0x98(%r14), %r15
jb 0x762c
movq %r14, %rdi
callq 0x5210
movsd %xmm0, 0x110(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x5210
movsd %xmm0, 0x108(%rsp)
cmpb $0x1, 0xf0(%r14)
jne 0x770c
movb $0x0, 0xf0(%r14)
leaq 0x100(%r14), %rdi
movq 0x98(%r14), %rsi
callq 0x5340
xorpd %xmm0, %xmm0
movsd %xmm0, 0xb8(%rsp)
movl $0x2, 0x2c(%rsp)
cmpq $0x0, 0x98(%r14)
je 0x772e
xorl %ebx, %ebx
movq 0xa0(%r14), %rax
movslq (%rax,%rbx,8), %rax
movq 0x20(%rsp), %rcx
movq (%rcx), %rcx
movq (%rcx,%rax,8), %rdi
movq (%rdi), %rax
movq %r14, %rsi
callq *(%rax)
movq 0x100(%r14), %rax
movsd %xmm0, (%rax,%rbx,8)
incq %rbx
cmpq 0x98(%r14), %rbx
jb 0x76d3
jmp 0x772e
movsd 0xf8(%r14), %xmm0
mulsd 0x2b3b(%rip), %xmm0     # 0xa258
movsd %xmm0, 0xb8(%rsp)
movl $0x14, 0x2c(%rsp)
movq $0x0, 0x120(%rsp)
movl $0x1, %eax
xorl %ecx, %ecx
movq %rcx, %rdx
shrq $0x1e, %rdx
xorl %ecx, %edx
imull $0x6c078965, %edx, %ecx # imm = 0x6C078965
addl %eax, %ecx
movq %rcx, 0x120(%rsp,%rax,8)
incq %rax
cmpq $0x270, %rax            # imm = 0x270
jne 0x7741
leaq 0x120(%rsp), %rax
movq $0x270, 0x1380(%rax) # imm = 0x270
leaq 0x100(%r14), %rax
movq %rax, 0x88(%rsp)
xorl %r15d, %r15d
xorpd %xmm0, %xmm0
movsd %xmm0, 0x80(%rsp)
movq 0x60(%rsp), %rdi
movq 0x68(%rsp), %rsi
leaq 0x120(%rsp), %rdx
callq 0x54e0
xorpd %xmm0, %xmm0
movsd %xmm0, 0x18(%rsp)
cmpq $0x0, 0x98(%r14)
je 0x7990
movq 0x60(%rsp), %rax
movq 0xa0(%r14), %rcx
movq 0x100(%r14), %rdx
movq 0xc0(%rsp), %rsi
movq 0xd8(%rsp), %rdi
xorl %r8d, %r8d
movq (%rax,%r8,8), %r9
movq (%rcx,%r8,8), %r10
movq (%rcx,%r9,8), %r11
movq %r11, (%rcx,%r8,8)
movq %r10, (%rcx,%r9,8)
movsd (%rsi,%r8,8), %xmm0
movsd (%rsi,%r9,8), %xmm1
movsd %xmm1, (%rsi,%r8,8)
movsd %xmm0, (%rsi,%r9,8)
movsd (%rdx,%r8,8), %xmm0
movsd (%rdx,%r9,8), %xmm1
movsd %xmm1, (%rdx,%r8,8)
movsd %xmm0, (%rdx,%r9,8)
movsd (%rdi,%r8,8), %xmm0
movsd (%rdi,%r9,8), %xmm1
movsd %xmm1, (%rdi,%r8,8)
movsd %xmm0, (%rdi,%r9,8)
incq %r8
movq 0x98(%r14), %r9
cmpq %r9, %r8
jb 0x77ec
testq %r9, %r9
je 0x7990
xorpd %xmm0, %xmm0
movsd %xmm0, 0x18(%rsp)
xorl %ebp, %ebp
movq 0xd8(%rsp), %rax
movsd (%rax,%rbp,8), %xmm1
xorpd %xmm0, %xmm0
ucomisd %xmm1, %xmm0
jae 0x7980
movsd %xmm1, (%rsp)
movq 0xa0(%r14), %rax
movq (%rax,%rbp,8), %rbx
movq 0x20(%rsp), %rax
movq (%rax), %rax
movslq %ebx, %rcx
movq (%rax,%rcx,8), %r12
movq 0x88(%rsp), %rax
movq (%rax), %rax
movsd (%rax,%rbp,8), %xmm0
movsd %xmm0, 0x30(%rsp)
movq (%r12), %rax
movq %r12, %rdi
leaq 0x48(%rsp), %rsi
leaq 0x90(%rsp), %rdx
callq *0x8(%rax)
movsd 0x30(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd (%r13,%rbx,8), %xmm0
movq 0xc0(%rsp), %rax
addsd (%rax,%rbp,8), %xmm0
movsd (%rsp), %xmm2
divsd %xmm2, %xmm1
movsd %xmm0, 0x30(%rsp)
subsd %xmm1, %xmm0
movapd 0xf0(%rsp), %xmm1
divsd %xmm2, %xmm1
callq 0x5250
movapd %xmm0, %xmm1
subsd 0x30(%rsp), %xmm1
ucomisd 0x2808(%rip), %xmm1     # 0xa130
jne 0x792c
jnp 0x7980
subsd (%r13,%rbx,8), %xmm0
movq 0xc0(%rsp), %rax
movsd %xmm0, (%rax,%rbp,8)
movq (%r12), %rax
movq %r12, %rdi
leaq 0x48(%rsp), %rsi
movsd %xmm1, 0x30(%rsp)
movapd %xmm1, %xmm0
callq *0x18(%rax)
movsd 0x30(%rsp), %xmm1
mulsd %xmm1, %xmm1
movsd (%rsp), %xmm0
mulsd %xmm0, %xmm1
mulsd %xmm0, %xmm1
movsd 0x18(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rsp)
incq %rbp
cmpq 0x98(%r14), %rbp
jb 0x786c
cmpb $0x0, 0xd9(%r14)
je 0x79ed
leaq 0x90(%rsp), %rdi
leaq 0x48(%rsp), %rbx
movq %rbx, %rsi
callq 0x53c0
addsd 0x110(%rsp), %xmm0
xorpd 0x26a0(%rip), %xmm0     # 0xa060
divsd 0x108(%rsp), %xmm0
movq %rbx, %rdi
movapd %xmm0, (%rsp)
callq 0x50f0
movsd 0x80(%rsp), %xmm0
addsd (%rsp), %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0xb8(%rsp), %xmm0
ucomisd 0x18(%rsp), %xmm0
seta %al
testl %r15d, %r15d
setne %cl
testb %al, %cl
jne 0x7a17
incl %r15d
cmpl 0x2c(%rsp), %r15d
jne 0x7797
movaps 0x2642(%rip), %xmm0     # 0xa060
xorps 0xf0(%rsp), %xmm0
movaps %xmm0, 0x30(%rsp)
leaq 0x78(%r14), %rbx
movsd 0x2789(%rip), %xmm0     # 0xa1c0
xorl %r12d, %r12d
leaq 0x48(%rsp), %r15
xorpd %xmm1, %xmm1
movsd %xmm0, 0x18(%rsp)
subsd %xmm1, %xmm0
movapd %xmm0, %xmm1
mulsd 0x80(%rsp), %xmm1
movq 0xa8(%rsp), %rax
addsd (%rax), %xmm1
movsd %xmm1, (%rax)
movq 0x98(%r14), %rax
xorpd %xmm1, %xmm1
movapd %xmm1, (%rsp)
testq %rax, %rax
je 0x7afb
movq 0xa0(%r14), %rcx
movapd %xmm1, (%rsp)
movq 0xc0(%rsp), %rdx
xorl %esi, %esi
movq (%rcx,%rsi,8), %rdi
movsd (%rdx,%rsi,8), %xmm1
mulsd %xmm0, %xmm1
addsd (%r13,%rdi,8), %xmm1
movsd %xmm1, (%r13,%rdi,8)
xorpd %xmm2, %xmm2
ucomisd %xmm1, %xmm2
jbe 0x7ac1
movsd (%rdx,%rsi,8), %xmm1
jmp 0x7adf
ucomisd %xmm2, %xmm1
movsd (%rdx,%rsi,8), %xmm1
jbe 0x7ad7
mulsd 0xf0(%rsp), %xmm1
jmp 0x7ae5
andpd 0x2571(%rip), %xmm1     # 0xa050
mulsd 0x30(%rsp), %xmm1
movapd (%rsp), %xmm2
addsd %xmm1, %xmm2
movapd %xmm2, (%rsp)
incq %rsi
cmpq %rsi, %rax
jne 0x7a95
movq 0x118(%rsp), %rsi
testq %rsi, %rsi
je 0x7b35
movq 0x48(%rsp), %rax
movq 0xb0(%rsp), %rcx
movq (%rcx), %rcx
xorl %edx, %edx
movsd (%rax,%rdx,8), %xmm1
mulsd %xmm0, %xmm1
addsd (%rcx,%rdx,8), %xmm1
movsd %xmm1, (%rcx,%rdx,8)
incq %rdx
cmpq %rdx, %rsi
jne 0x7b1a
movq 0x78(%rsp), %rdi
movq (%rdi), %rax
movq 0xb0(%rsp), %rsi
movq %r14, %rdx
movq %rbx, %rcx
movq 0x20(%rsp), %r8
callq *0x10(%rax)
movq %r15, %rdi
movq %r14, %rsi
callq 0x53c0
movapd (%rsp), %xmm1
addsd %xmm0, %xmm1
xorpd %xmm0, %xmm0
ucomisd %xmm1, %xmm0
ja 0x7b96
movsd 0x18(%rsp), %xmm1
movapd %xmm1, %xmm2
mulsd 0x269d(%rip), %xmm2     # 0xa220
incl %r12d
movapd %xmm2, %xmm0
cmpl $0x14, %r12d
jne 0x7a43
jmp 0x7b9c
movsd 0x18(%rsp), %xmm2
movsd %xmm2, (%rsp)
movq %r14, %rdi
movq 0xa8(%rsp), %rsi
movq 0x78(%rsp), %rdx
movq 0x20(%rsp), %rcx
callq 0x55d0
movsd (%rsp), %xmm2
ucomisd 0x25f8(%rip), %xmm2     # 0xa1c0
jne 0x7bcc
jnp 0x7c03
movq 0x48(%rsp), %rax
movq 0x50(%rsp), %rcx
subq %rax, %rcx
je 0x7c03
sarq $0x3, %rcx
cmpq $0x1, %rcx
adcq $0x0, %rcx
xorl %edx, %edx
movsd (%rax,%rdx,8), %xmm1
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, (%rax,%rdx,8)
incq %rdx
cmpq %rdx, %rcx
jne 0x7be9
cmpq $0x0, 0x98(%r14)
je 0x7cb6
xorl %r13d, %r13d
leaq 0x48(%rsp), %rbx
leaq 0x90(%rsp), %r15
movq 0xa0(%r14), %rax
movslq (%rax,%r13,8), %rax
movq 0x20(%rsp), %rcx
movq (%rcx), %rcx
movq (%rcx,%rax,8), %r12
movq (%r12), %rax
movq %r12, %rdi
movq %r14, %rsi
callq *(%rax)
movsd %xmm0, (%rsp)
movq 0x88(%rsp), %rax
movq (%rax), %rax
movsd (%rax,%r13,8), %xmm0
movsd %xmm0, 0x30(%rsp)
movq (%r12), %rax
movq %r12, %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq *0x8(%rax)
movsd 0x30(%rsp), %xmm1
addsd %xmm0, %xmm1
movq 0x100(%r14), %rax
movsd (%rsp), %xmm0
movsd %xmm0, (%rax,%r13,8)
subsd %xmm1, %xmm0
mulsd %xmm0, %xmm0
addsd 0xf8(%r14), %xmm0
movsd %xmm0, 0xf8(%r14)
incq %r13
cmpq 0x98(%r14), %r13
jb 0x7c21
movq 0x88(%rsp), %rdi
callq 0x5410
movsd %xmm0, (%rsp)
movq 0xd8(%rsp), %rdi
testq %rdi, %rdi
je 0x7ce5
movq 0xe8(%rsp), %rsi
subq %rdi, %rsi
callq 0x5330
movq 0x90(%rsp), %rdi
testq %rdi, %rdi
je 0x7d02
movq 0xa0(%rsp), %rsi
subq %rdi, %rsi
callq 0x5330
movq 0x60(%rsp), %rdi
testq %rdi, %rdi
je 0x7d19
movq 0x70(%rsp), %rsi
subq %rdi, %rsi
callq 0x5330
movq 0x48(%rsp), %rdi
testq %rdi, %rdi
je 0x7d30
movq 0x58(%rsp), %rsi
subq %rdi, %rsi
callq 0x5330
movq 0xc0(%rsp), %rdi
testq %rdi, %rdi
je 0x7d4d
movq 0xd0(%rsp), %rsi
subq %rdi, %rsi
callq 0x5330
movapd 0xf0(%rsp), %xmm0
movapd %xmm0, %xmm2
movsd (%rsp), %xmm1
divsd %xmm1, %xmm2
cmpltsd %xmm1, %xmm0
andpd %xmm0, %xmm2
movsd 0x244c(%rip), %xmm1     # 0xa1c0
andnpd %xmm1, %xmm0
orpd %xmm2, %xmm0
addq $0x14a8, %rsp           # imm = 0x14A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7d9a
movq %rax, %rbx
jmp 0x7de2
jmp 0x7da9
movq %rax, %rbx
jmp 0x7e2d
movq %rax, %rbx
jmp 0x7dff
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
jmp 0x7dc2
movq %rax, %rbx
movq 0xd8(%rsp), %rdi
testq %rdi, %rdi
je 0x7de2
movq 0xe8(%rsp), %rsi
subq %rdi, %rsi
callq 0x5330
movq 0x90(%rsp), %rdi
testq %rdi, %rdi
je 0x7dff
movq 0xa0(%rsp), %rsi
subq %rdi, %rsi
callq 0x5330
movq 0x60(%rsp), %rdi
testq %rdi, %rdi
je 0x7e16
movq 0x70(%rsp), %rsi
subq %rdi, %rsi
callq 0x5330
movq 0x48(%rsp), %rdi
testq %rdi, %rdi
je 0x7e2d
movq 0x58(%rsp), %rsi
subq %rdi, %rsi
callq 0x5330
movq 0xc0(%rsp), %rdi
testq %rdi, %rdi
je 0x7e4a
movq 0xd0(%rsp), %rsi
subq %rdi, %rsi
callq 0x5330
movq %rbx, %rdi
callq 0x5580