// File: /workspace/github_c_makefile_star2_O0/zpole[P]IICV/vl/svm.c
// Function: vl_svm_logistic_dca_update
double
vl_svm_logistic_dca_update (double alpha, double inner, double norm2, double label) {
  /*
   The goal is to solve the problem

   min_delta A/2 delta^2 + B delta + l*(-alpha - delta|y),  -1 <= - y (alpha+delta) <= 0

   where A = norm2, B = inner, and y = label. To simplify the notation, we set

     f(beta) = beta * log(beta) + (1 - beta) * log(1 - beta)

   where beta = y(alpha + delta) such that

     l*(-alpha - delta |y) = f(beta).

   Hence 0 <= beta <= 1, delta = + y beta - alpha. Substituting

     min_beta A/2 beta^2 + y (B - A alpha) beta + f(beta) + const

   The Newton step is then given by

     beta = beta - (A beta + y(B - A alpha) + df) / (A + ddf).

   However, the function is singluar for beta=0 and beta=1 (infinite
   first and second order derivatives). Since the function is monotonic
   (second derivarive always strictly greater than zero) and smooth,
   we canuse bisection to find the zero crossing of the first derivative.
   Once one is sufficiently close to the optimum, a one or two Newton
   steps are sufficien to land on it with excellent accuracy.
   */

  double  df, ddf, der, dder ;
  vl_index t ;

  /* bisection */
  double beta1 = 0 ;
  double beta2 = 1 ;
  double beta = 0.5 ;

  for (t = 0 ; t < 5 ; ++t) {
    df = log(beta) - log(1-beta) ;
    der = norm2 * beta + label * (inner - norm2*alpha) + df ;
    if (der >= 0) {
      beta2 = beta ;
    } else {
      beta1 = beta ;
    }
    beta = 0.5 * (beta1 + beta2) ;
  }

#if 1
  /* a final Newton step, but not too close to the singularities */
  for (t = 0 ; (t < 2) & (beta > VL_EPSILON_D) & (beta < 1-VL_EPSILON_D) ; ++t) {
    df = log(beta) - log(1-beta) ;
    ddf = 1 / (beta * (1-beta)) ;
    der = norm2 * beta + label * (inner - norm2*alpha) + df ;
    dder = norm2 + ddf ;
    beta -= der / dder ;
    beta = VL_MAX(0, VL_MIN(1, beta)) ;
  }
#endif

  return label * beta - alpha ;
}

// Assembly:
subq $0x88, %rsp
movsd %xmm0, 0x80(%rsp)
movsd %xmm1, 0x78(%rsp)
movsd %xmm2, 0x70(%rsp)
movsd %xmm3, 0x68(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x38(%rsp)
movsd 0x3445(%rip), %xmm0     # 0x590d8
movsd %xmm0, 0x30(%rsp)
movsd 0x33df(%rip), %xmm0     # 0x59080
movsd %xmm0, 0x28(%rsp)
movq $0x0, 0x40(%rsp)
cmpq $0x5, 0x40(%rsp)
jge 0x55dab
movsd 0x28(%rsp), %xmm0
callq 0x94c0
movsd %xmm0, 0x20(%rsp)
movsd 0x3403(%rip), %xmm0     # 0x590d8
subsd 0x28(%rsp), %xmm0
callq 0x94c0
movaps %xmm0, %xmm1
movsd 0x20(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x70(%rsp), %xmm0
movsd 0x28(%rsp), %xmm2
movsd 0x68(%rsp), %xmm1
movsd 0x78(%rsp), %xmm4
movsd 0x70(%rsp), %xmm3
movsd 0x80(%rsp), %xmm5
movq %xmm3, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm3
mulsd %xmm5, %xmm3
addsd %xmm4, %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
addsd 0x60(%rsp), %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x50(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x55d6e
movsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
jmp 0x55d7a
movsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
movsd 0x38(%rsp), %xmm1
addsd 0x30(%rsp), %xmm1
movsd 0x32f2(%rip), %xmm0     # 0x59080
mulsd %xmm1, %xmm0
movsd %xmm0, 0x28(%rsp)
movq 0x40(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x40(%rsp)
jmp 0x55cb0
movq $0x0, 0x40(%rsp)
cmpq $0x2, 0x40(%rsp)
setl %al
andb $0x1, %al
movzbl %al, %eax
movsd 0x28(%rsp), %xmm0
movsd 0x3bf8(%rip), %xmm1     # 0x599c8
ucomisd %xmm1, %xmm0
seta %cl
andb $0x1, %cl
movzbl %cl, %ecx
andl %ecx, %eax
movsd 0x43f9(%rip), %xmm0     # 0x5a1e0
ucomisd 0x28(%rsp), %xmm0
seta %cl
andb $0x1, %cl
movzbl %cl, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x55f90
movsd 0x28(%rsp), %xmm0
callq 0x94c0
movsd %xmm0, 0x18(%rsp)
movsd 0x32be(%rip), %xmm0     # 0x590d8
subsd 0x28(%rsp), %xmm0
callq 0x94c0
movaps %xmm0, %xmm1
movsd 0x18(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x28(%rsp), %xmm1
movsd 0x3292(%rip), %xmm0     # 0x590d8
subsd 0x28(%rsp), %xmm0
mulsd %xmm0, %xmm1
movsd 0x3280(%rip), %xmm0     # 0x590d8
divsd %xmm1, %xmm0
movsd %xmm0, 0x58(%rsp)
movsd 0x70(%rsp), %xmm0
movsd 0x28(%rsp), %xmm2
movsd 0x68(%rsp), %xmm1
movsd 0x78(%rsp), %xmm4
movsd 0x70(%rsp), %xmm3
movsd 0x80(%rsp), %xmm5
movq %xmm3, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm3
mulsd %xmm5, %xmm3
addsd %xmm4, %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
addsd 0x60(%rsp), %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x70(%rsp), %xmm0
addsd 0x58(%rsp), %xmm0
movsd %xmm0, 0x48(%rsp)
movsd 0x50(%rsp), %xmm1
divsd 0x48(%rsp), %xmm1
movsd 0x28(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x28(%rsp)
movsd 0x28(%rsp), %xmm0
movsd 0x31dc(%rip), %xmm1     # 0x590d8
ucomisd %xmm1, %xmm0
jbe 0x55f12
movsd 0x31ce(%rip), %xmm0     # 0x590d8
movsd %xmm0, 0x10(%rsp)
jmp 0x55f1e
movsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0x10(%rsp), %xmm1
xorps %xmm0, %xmm0
ucomisd %xmm1, %xmm0
jbe 0x55f38
xorps %xmm0, %xmm0
movsd %xmm0, 0x8(%rsp)
jmp 0x55f71
movsd 0x28(%rsp), %xmm0
movsd 0x3192(%rip), %xmm1     # 0x590d8
ucomisd %xmm1, %xmm0
jbe 0x55f5b
movsd 0x3184(%rip), %xmm0     # 0x590d8
movsd %xmm0, (%rsp)
jmp 0x55f66
movsd 0x28(%rsp), %xmm0
movsd %xmm0, (%rsp)
movsd (%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
movq 0x40(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x40(%rsp)
jmp 0x55db4
movsd 0x68(%rsp), %xmm0
movsd 0x28(%rsp), %xmm2
movsd 0x80(%rsp), %xmm1
movq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
addq $0x88, %rsp
retq
nopl (%rax)