// File: /workspace/github_c_makefile_star2_O3/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 0x183f(%rip), %xmm0     # 0x32270
movsd 0x17a7(%rip), %xmm2     # 0x321e0
movl $0x5, %ebx
movsd %xmm0, 0x28(%rsp)
xorpd %xmm1, %xmm1
movapd %xmm1, 0x40(%rsp)
movapd %xmm2, 0x10(%rsp)
movapd %xmm2, %xmm0
callq 0x9430
movsd %xmm0, 0x8(%rsp)
movsd 0x1805(%rip), %xmm0     # 0x32270
subsd 0x10(%rsp), %xmm0
callq 0x9430
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 0x158e(%rip), %xmm0     # 0x32030
jb 0x30aaa
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 0x170d(%rip), %xmm2     # 0x321e0
decq %rbx
jne 0x30a48
movsd 0x29e4(%rip), %xmm0     # 0x334c8
ucomisd %xmm2, %xmm0
jbe 0x30bad
ucomisd 0x20d2(%rip), %xmm2     # 0x32bc8
jbe 0x30bad
movb $0x1, %bl
movapd %xmm2, 0x10(%rsp)
movapd %xmm2, %xmm0
callq 0x9430
movsd %xmm0, 0x40(%rsp)
movsd 0x1755(%rip), %xmm0     # 0x32270
subsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x9430
movsd 0x40(%rsp), %xmm5
subsd %xmm0, %xmm5
movapd 0x10(%rsp), %xmm3
movsd 0x8(%rsp), %xmm1
mulsd %xmm3, %xmm1
movsd 0x1722(%rip), %xmm4     # 0x32270
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
movsd 0x2936(%rip), %xmm0     # 0x334c8
ucomisd %xmm2, %xmm0
jbe 0x30bad
testb $0x1, %bl
je 0x30bad
xorl %ebx, %ebx
ucomisd 0x2021(%rip), %xmm2     # 0x32bc8
ja 0x30afe
movsd 0x58(%rsp), %xmm0
mulsd %xmm2, %xmm0
subsd 0x50(%rsp), %xmm0
addq $0x60, %rsp
popq %rbx
retq