// File: /workspace/github_c_makefile_star2_O1/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 0x253b(%rip), %xmm0     # 0x33260
movsd 0x24a3(%rip), %xmm2     # 0x331d0
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 0x2501(%rip), %xmm0     # 0x33260
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 0x229a(%rip), %xmm0     # 0x33030
jb 0x30d9e
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 0x2409(%rip), %xmm2     # 0x331d0
decq %rbx
jne 0x30d3c
movsd 0x3710(%rip), %xmm0     # 0x344e8
ucomisd %xmm2, %xmm0
jbe 0x30ea5
ucomisd 0x2dee(%rip), %xmm2     # 0x33bd8
jbe 0x30ea5
xorl %ebx, %ebx
movapd %xmm2, 0x10(%rsp)
movapd %xmm2, %xmm0
callq 0x9430
movsd %xmm0, 0x40(%rsp)
movsd 0x2451(%rip), %xmm0     # 0x33260
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 0x241e(%rip), %xmm4     # 0x33260
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
subq $0x1, %rbx
setb %al
movsd 0x365b(%rip), %xmm0     # 0x344e8
ucomisd %xmm2, %xmm0
jbe 0x30ea5
testb %al, %al
je 0x30ea5
ucomisd 0x2d39(%rip), %xmm2     # 0x33bd8
ja 0x30df2
movsd 0x58(%rsp), %xmm0
mulsd %xmm2, %xmm0
subsd 0x50(%rsp), %xmm0
addq $0x60, %rsp
popq %rbx
retq