// File: /workspace/github_c_makefile_star2_O3/zpole[P]IICV/vl/imopv.c
// Function: vl_image_distance_transform_f
VL_EXPORT void
VL_XCAT(vl_image_distance_transform_,SFX)
(T const * image,
 vl_size numColumns,
 vl_size numRows,
 vl_size columnStride,
 vl_size rowStride,
 T * distanceTransform,
 vl_uindex * indexes,
 T coeff,
 T offset)
{
  /* Each image pixel corresponds to a parabola. The algorithm scans
   such parabolas from left to right, keeping track of which
   parabolas belong to the lower envelope and in which interval. There are
   NUM active parabolas, FROM stores the beginning of the interval
   for which a certain parabola is part of the envoelope, and WHICH store
   the index of the parabola (that is, the pixel x from which the parabola
   originated).
   */
  vl_uindex x, y ;
  T * from = vl_malloc (sizeof(T) * (numColumns + 1)) ;
  T * base = vl_malloc (sizeof(T) * numColumns) ;
  vl_uindex * baseIndexes = vl_malloc (sizeof(vl_uindex) * numColumns) ;
  vl_uindex * which = vl_malloc (sizeof(vl_uindex) * numColumns) ;
  vl_uindex num = 0 ;

  for (y = 0 ; y < numRows ; ++y) {
    num = 0 ;
    for (x = 0 ; x < numColumns ; ++x) {
      T r = image[x  * columnStride + y * rowStride] ;
      T x2 = x * x ;
#if (FLT == VL_TYPE_FLOAT)
      T from_ = - VL_INFINITY_F ;
#else
      T from_ = - VL_INFINITY_D ;
#endif

      /*
       Add next parabola (there are NUM so far). The algorithm finds
       intersection INTERS with the previously added parabola. If
       the intersection is on the right of the "starting point" of
       this parabola, then the previous parabola is kept, and the
       new one is added to its right. Otherwise the new parabola
       "eats" the old one, which gets deleted and the check is
       repeated with the parabola added before the deleted one.
       */

      while (num >= 1) {
        vl_uindex x_ = which[num - 1] ;
        T x2_ = x_ * x_ ;
        T r_ = image[x_ * columnStride + y * rowStride] ;
        T inters ;
        if (r == r_) {
          /* handles the case r = r_ = \pm inf */
          inters = (x + x_) / 2.0 + offset ;
        }
#if (FLT == VL_TYPE_FLOAT)
        else if (coeff > VL_EPSILON_F)
#else
        else if (coeff > VL_EPSILON_D)
#endif
        {
          inters = ((r - r_) + coeff * (x2 - x2_)) / (x - x_) / (2*coeff) + offset ;
        } else {
          /* If coeff is very small, the parabolas are flat (= lines).
           In this case the previous parabola should be deleted if the current
           pixel has lower score */
#if (FLT == VL_TYPE_FLOAT)
          inters = (r < r_) ? - VL_INFINITY_F : VL_INFINITY_F ;
#else
          inters = (r < r_) ? - VL_INFINITY_D : VL_INFINITY_D ;
#endif
        }
        if (inters <= from [num - 1]) {
          /* delete a previous parabola */
          -- num ;
        } else {
          /* accept intersection */
          from_ = inters ;
          break ;
        }
      }

      /* add a new parabola */
      which[num] = x ;
      from[num] = from_ ;
      base[num] = r ;
      if (indexes) baseIndexes[num] = indexes[x  * columnStride + y * rowStride] ;
      num ++ ;
    } /* next column */

#if (FLT == VL_TYPE_FLOAT)
    from[num] = VL_INFINITY_F ;
#else
    from[num] = VL_INFINITY_D ;
#endif

    /* fill in */
    num = 0 ;
    for (x = 0 ; x < numColumns ; ++x) {
      double delta ;
      while (x >= from[num + 1]) ++ num ;
      delta = (double) x - (double) which[num] - offset ;
      distanceTransform[x  * columnStride + y * rowStride]
      = base[num] + coeff * delta * delta ;
      if (indexes) {
        indexes[x  * columnStride + y * rowStride]
        = baseIndexes[num] ;
      }
    }
  } /* next row */

  vl_free (from) ;
  vl_free (which) ;
  vl_free (base) ;
  vl_free (baseIndexes) ;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movss %xmm1, 0x1c(%rsp)
movss %xmm0, 0xc(%rsp)
movq %r9, 0x38(%rsp)
movq %r8, 0x30(%rsp)
movq %rcx, %r15
movq %rdx, 0x20(%rsp)
movq %rsi, %r13
movq %rdi, 0x28(%rsp)
movq 0x80(%rsp), %rbx
leaq (,%rsi,4), %r14
leaq 0x4(,%rsi,4), %rdi
callq 0x95b0
movq %rax, %r12
movq %r14, %rdi
callq 0x95b0
movq %rax, %r14
leaq (,%r13,8), %rbp
movq %rbp, %rdi
callq 0x95b0
movq %rax, 0x10(%rsp)
movq %rbp, %rdi
callq 0x95b0
movss 0x1c(%rsp), %xmm15
movq %rax, %rbp
cmpq $0x0, 0x20(%rsp)
je 0x18c43
movss 0xc(%rsp), %xmm2
movaps %xmm2, %xmm0
addss %xmm2, %xmm0
xorps %xmm1, %xmm1
cvtss2sd %xmm15, %xmm1
cvtss2sd %xmm2, %xmm2
xorl %edx, %edx
movss 0x19bc5(%rip), %xmm3    # 0x32510
movq 0x1982d(%rip), %xmm4    # 0x32180
movapd 0x19835(%rip), %xmm5    # 0x32190
movapd 0x1982d(%rip), %xmm6    # 0x32190
movsd 0x19875(%rip), %xmm7    # 0x321e0
movss 0x199f0(%rip), %xmm8    # 0x32364
leaq 0x1a245(%rip), %rcx     # 0x32bc0
testq %r13, %r13
movq %rdx, 0x40(%rsp)
je 0x18c28
imulq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rax
leaq (%rax,%rdx,4), %rsi
xorl %edi, %edi
xorl %r8d, %r8d
movq %rdi, %r9
imulq %rdi, %r9
testq %r9, %r9
js 0x189b4
xorps %xmm9, %xmm9
cvtsi2ss %r9, %xmm9
jmp 0x189cf
movq %r9, %r10
shrq %r10
andl $0x1, %r9d
orq %r10, %r9
xorps %xmm9, %xmm9
cvtsi2ss %r9, %xmm9
addss %xmm9, %xmm9
movq %rdi, %r9
imulq %r15, %r9
addq %rdx, %r9
movq 0x28(%rsp), %rax
movss (%rax,%r9,4), %xmm10
incq %r8
movq %r8, %r10
movq %r10, %r8
cmpq $0x1, %r10
je 0x18b05
movq -0x10(%rbp,%r8,8), %r10
movq %r10, %r11
imulq %r10, %r11
testq %r11, %r11
js 0x18a13
xorps %xmm11, %xmm11
cvtsi2ss %r11, %xmm11
jmp 0x18a2e
movq %r11, %rax
shrq %rax
andl $0x1, %r11d
orq %rax, %r11
xorps %xmm11, %xmm11
cvtsi2ss %r11, %xmm11
addss %xmm11, %xmm11
movq %r10, %rax
imulq %r15, %rax
movss (%rsi,%rax,4), %xmm12
ucomiss %xmm12, %xmm10
jne 0x18a75
jp 0x18a75
addq %rdi, %r10
movq %r10, %xmm11
punpckldq %xmm4, %xmm11   # xmm11 = xmm11[0],xmm4[0],xmm11[1],xmm4[1]
subpd %xmm6, %xmm11
movapd %xmm11, %xmm12
unpckhpd %xmm11, %xmm12          # xmm12 = xmm12[1],xmm11[1]
addsd %xmm11, %xmm12
mulsd %xmm7, %xmm12
addsd %xmm1, %xmm12
cvtsd2ss %xmm12, %xmm12
jmp 0x18aee
movss 0xc(%rsp), %xmm13
ucomiss %xmm8, %xmm13
jbe 0x18a95
movq %rdi, %r11
subq %r10, %r11
js 0x18aa6
xorps %xmm13, %xmm13
cvtsi2ss %r11, %xmm13
jmp 0x18ac1
xorl %eax, %eax
ucomiss %xmm10, %xmm12
seta %al
movss (%rcx,%rax,4), %xmm12
jmp 0x18aee
movq %r11, %rax
shrq %rax
andl $0x1, %r11d
orq %rax, %r11
xorps %xmm13, %xmm13
cvtsi2ss %r11, %xmm13
addss %xmm13, %xmm13
movaps %xmm10, %xmm14
subss %xmm12, %xmm14
movaps %xmm9, %xmm12
subss %xmm11, %xmm12
mulss 0xc(%rsp), %xmm12
addss %xmm14, %xmm12
divss %xmm13, %xmm12
divss %xmm0, %xmm12
addss %xmm15, %xmm12
movss -0x8(%r12,%r8,4), %xmm11
leaq -0x1(%r8), %r10
ucomiss %xmm12, %xmm11
jae 0x189ea
jmp 0x18b09
movaps %xmm3, %xmm12
movq %rdi, -0x8(%rbp,%r8,8)
movss %xmm12, -0x4(%r12,%r8,4)
movss %xmm10, -0x4(%r14,%r8,4)
testq %rbx, %rbx
je 0x18b2f
movq (%rbx,%r9,8), %rax
movq 0x10(%rsp), %r9
movq %rax, -0x8(%r9,%r8,8)
incq %rdi
cmpq %r13, %rdi
jne 0x1899d
movl $0x7f800000, (%r12,%r8,4) # imm = 0x7F800000
xorl %esi, %esi
xorl %edi, %edi
movq 0x38(%rsp), %r9
testq %rsi, %rsi
js 0x18b5c
xorps %xmm9, %xmm9
cvtsi2ss %rsi, %xmm9
jmp 0x18b7a
movq %rsi, %rax
shrq %rax
movl %esi, %r8d
andl $0x1, %r8d
orq %rax, %r8
xorps %xmm9, %xmm9
cvtsi2ss %r8, %xmm9
addss %xmm9, %xmm9
decq %rdi
ucomiss 0x8(%r12,%rdi,4), %xmm9
leaq 0x1(%rdi), %rdi
jae 0x18b7d
movq %rsi, %r8
imulq %r15, %r8
addq %rdx, %r8
movq %rsi, %xmm9
punpckldq %xmm4, %xmm9    # xmm9 = xmm9[0],xmm4[0],xmm9[1],xmm4[1]
subpd %xmm5, %xmm9
movapd %xmm9, %xmm10
unpckhpd %xmm9, %xmm10           # xmm10 = xmm10[1],xmm9[1]
addsd %xmm9, %xmm10
movq (%rbp,%rdi,8), %xmm9
punpckldq %xmm4, %xmm9    # xmm9 = xmm9[0],xmm4[0],xmm9[1],xmm4[1]
subpd %xmm5, %xmm9
movapd %xmm9, %xmm11
unpckhpd %xmm9, %xmm11           # xmm11 = xmm11[1],xmm9[1]
addsd %xmm9, %xmm11
subsd %xmm11, %xmm10
subsd %xmm1, %xmm10
xorps %xmm9, %xmm9
cvtss2sd (%r14,%rdi,4), %xmm9
movapd %xmm10, %xmm11
mulsd %xmm2, %xmm11
mulsd %xmm10, %xmm11
addsd %xmm9, %xmm11
xorps %xmm9, %xmm9
cvtsd2ss %xmm11, %xmm9
movss %xmm9, (%r9,%r8,4)
testq %rbx, %rbx
je 0x18c1a
movq 0x10(%rsp), %rax
movq (%rax,%rdi,8), %rax
movq %rax, (%rbx,%r8,8)
incq %rsi
cmpq %r13, %rsi
jne 0x18b4c
jmp 0x18c30
movl $0x7f800000, (%r12)     # imm = 0x7F800000
movq 0x40(%rsp), %rdx
incq %rdx
cmpq 0x20(%rsp), %rdx
jne 0x1897b
movq %r12, %rdi
callq 0x9580
movq %rbp, %rdi
callq 0x9580
movq %r14, %rdi
callq 0x9580
movq 0x10(%rsp), %rdi
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x9580