// File: /workspace/github_c_makefile_star2_O2/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:
pushq %rbx
subq $0x60, %rsp
movsd %xmm2, 0x38(%rsp)
movsd %xmm0, 0x50(%rsp)
mulsd %xmm0, %xmm2
subsd %xmm2, %xmm1
movsd %xmm3, 0x58(%rsp)
mulsd %xmm3, %xmm1
movsd %xmm1, 0x30(%rsp)
movsd 0x23ba(%rip), %xmm2     # 0x2d1c0
movsd 0x242a(%rip), %xmm0     # 0x2d238
pushq $0x5
popq %rbx
xorpd %xmm1, %xmm1
movsd %xmm0, 0x28(%rsp)
subq $0x1, %rbx
jb 0x2aeb5
movapd %xmm1, 0x40(%rsp)
movapd %xmm2, %xmm0
movapd %xmm2, 0x10(%rsp)
callq 0x9450
movsd %xmm0, 0x8(%rsp)
movsd 0x23f0(%rip), %xmm0     # 0x2d238
subsd 0x10(%rsp), %xmm0
callq 0x9450
movapd 0x10(%rsp), %xmm2
movsd 0x8(%rsp), %xmm1
subsd %xmm0, %xmm1
movsd 0x38(%rsp), %xmm0
mulsd %xmm2, %xmm0
addsd 0x30(%rsp), %xmm0
addsd %xmm1, %xmm0
ucomisd 0x2181(%rip), %xmm0     # 0x2d000
jb 0x2ae87
movsd %xmm2, 0x28(%rsp)
xorpd %xmm1, %xmm1
cmpnlesd %xmm0, %xmm1
andpd %xmm1, %xmm2
andnpd 0x40(%rsp), %xmm1
orpd %xmm2, %xmm1
movapd %xmm1, %xmm2
addsd 0x28(%rsp), %xmm2
mulsd 0x2310(%rip), %xmm2     # 0x2d1c0
jmp 0x2ae1b
xorl %ebx, %ebx
movsd 0x3531(%rip), %xmm0     # 0x2e3f0
ucomisd %xmm2, %xmm0
jbe 0x2af75
cmpq $0x1, %rbx
ja 0x2af75
ucomisd 0x2cbd(%rip), %xmm2     # 0x2db98
jbe 0x2af75
movapd %xmm2, %xmm0
movapd %xmm2, 0x10(%rsp)
callq 0x9450
movsd %xmm0, 0x40(%rsp)
movsd 0x233a(%rip), %xmm0     # 0x2d238
subsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x9450
movsd 0x40(%rsp), %xmm5
subsd %xmm0, %xmm5
movapd 0x10(%rsp), %xmm3
movsd 0x8(%rsp), %xmm1
mulsd %xmm3, %xmm1
movsd 0x2307(%rip), %xmm4     # 0x2d238
movapd %xmm4, %xmm0
divsd %xmm1, %xmm0
movsd 0x38(%rsp), %xmm2
movapd %xmm2, %xmm1
mulsd %xmm3, %xmm1
addsd 0x30(%rsp), %xmm1
addsd %xmm5, %xmm1
addsd %xmm2, %xmm0
divsd %xmm0, %xmm1
subsd %xmm1, %xmm3
movapd %xmm4, %xmm0
minsd %xmm3, %xmm0
xorpd %xmm2, %xmm2
maxsd %xmm0, %xmm2
incq %rbx
jmp 0x2aeb7
movsd 0x58(%rsp), %xmm0
mulsd %xmm2, %xmm0
subsd 0x50(%rsp), %xmm0
addq $0x60, %rsp
popq %rbx
retq