// File: /workspace/github_c_makefile_star2_O1/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 $0x38, %rsp
movss %xmm1, 0x4(%rsp)
movss %xmm0, (%rsp)
movq %r9, 0x30(%rsp)
movq %r8, 0x18(%rsp)
movq %rcx, %r15
movq %rdx, 0x10(%rsp)
movq %rsi, %r13
movq %rdi, 0x28(%rsp)
movq 0x70(%rsp), %rbx
leaq (,%rsi,4), %r12
leaq 0x4(,%rsi,4), %rdi
callq 0x95b0
movq %rax, %r14
movq %r12, %rdi
callq 0x95b0
movq %rax, %r12
leaq (,%r13,8), %rbp
movq %rbp, %rdi
callq 0x95b0
movq %rax, 0x8(%rsp)
movq %rbp, %rdi
callq 0x95b0
movq %rax, %rbp
cmpq $0x0, 0x10(%rsp)
je 0x18d58
movss (%rsp), %xmm2
movaps %xmm2, %xmm0
addss %xmm2, %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0x4(%rsp), %xmm1
cvtss2sd %xmm2, %xmm2
xorl %edx, %edx
movq 0x1a74b(%rip), %xmm3    # 0x33180
movapd 0x1a753(%rip), %xmm4    # 0x33190
movss 0x1aacb(%rip), %xmm5    # 0x33510
movapd 0x1a743(%rip), %xmm6    # 0x33190
movsd 0x1a77b(%rip), %xmm7    # 0x331d0
movss 0x1a8f6(%rip), %xmm8    # 0x33354
leaq 0x1b16b(%rip), %rcx     # 0x33bd0
testq %r13, %r13
movq %rdx, 0x20(%rsp)
je 0x18c43
imulq 0x18(%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 0x18a9e
xorps %xmm9, %xmm9
cvtsi2ss %r9, %xmm9
jmp 0x18ab9
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
movaps %xmm5, %xmm11
testq %r8, %r8
je 0x18c08
movq -0x8(%rbp,%r8,8), %r10
movq %r10, %r11
imulq %r10, %r11
testq %r11, %r11
js 0x18af7
xorps %xmm12, %xmm12
cvtsi2ss %r11, %xmm12
jmp 0x18b12
movq %r11, %rax
shrq %rax
andl $0x1, %r11d
orq %rax, %r11
xorps %xmm12, %xmm12
cvtsi2ss %r11, %xmm12
addss %xmm12, %xmm12
movq %r10, %rax
imulq %r15, %rax
movss (%rsi,%rax,4), %xmm13
ucomiss %xmm13, %xmm10
jne 0x18b59
jp 0x18b59
addq %rdi, %r10
movq %r10, %xmm12
punpckldq %xmm3, %xmm12   # xmm12 = xmm12[0],xmm3[0],xmm12[1],xmm3[1]
subpd %xmm6, %xmm12
movapd %xmm12, %xmm13
unpckhpd %xmm12, %xmm13          # xmm13 = xmm13[1],xmm12[1]
addsd %xmm12, %xmm13
mulsd %xmm7, %xmm13
addsd %xmm1, %xmm13
cvtsd2ss %xmm13, %xmm13
jmp 0x18bd2
movss (%rsp), %xmm14
ucomiss %xmm8, %xmm14
jbe 0x18b78
movq %rdi, %r11
subq %r10, %r11
js 0x18b89
xorps %xmm14, %xmm14
cvtsi2ss %r11, %xmm14
jmp 0x18ba4
xorl %eax, %eax
ucomiss %xmm10, %xmm13
seta %al
movss (%rcx,%rax,4), %xmm13
jmp 0x18bd2
movq %r11, %rax
shrq %rax
andl $0x1, %r11d
orq %rax, %r11
xorps %xmm14, %xmm14
cvtsi2ss %r11, %xmm14
addss %xmm14, %xmm14
movaps %xmm10, %xmm15
subss %xmm13, %xmm15
movaps %xmm9, %xmm13
subss %xmm12, %xmm13
mulss (%rsp), %xmm13
addss %xmm15, %xmm13
divss %xmm14, %xmm13
divss %xmm0, %xmm13
addss 0x4(%rsp), %xmm13
leaq -0x1(%r8), %r10
movss -0x4(%r14,%r8,4), %xmm14
ucomiss %xmm13, %xmm14
jb 0x18be6
movq %r10, %r8
movaps %xmm13, %xmm12
cmpnless %xmm14, %xmm12
andps %xmm12, %xmm13
andnps %xmm11, %xmm12
orps %xmm13, %xmm12
movaps %xmm12, %xmm11
jae 0x18ad2
jmp 0x18c0f
movaps %xmm11, %xmm12
xorl %r8d, %r8d
movq %rdi, (%rbp,%r8,8)
movss %xmm12, (%r14,%r8,4)
movss %xmm10, (%r12,%r8,4)
testq %rbx, %rbx
je 0x18c32
movq (%rbx,%r9,8), %rax
movq 0x8(%rsp), %r9
movq %rax, (%r9,%r8,8)
incq %r8
incq %rdi
cmpq %r13, %rdi
jne 0x18a87
jmp 0x18c46
xorl %r8d, %r8d
movl $0x7f800000, (%r14,%r8,4) # imm = 0x7F800000
testq %r13, %r13
movq 0x30(%rsp), %r9
je 0x18d45
movq 0x20(%rsp), %rdx
imulq 0x18(%rsp), %rdx
xorl %esi, %esi
xorl %edi, %edi
testq %rsi, %rsi
js 0x18c7b
xorps %xmm9, %xmm9
cvtsi2ss %rsi, %xmm9
jmp 0x18c99
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(%r14,%rdi,4), %xmm9
leaq 0x1(%rdi), %rdi
jae 0x18c9c
movq %rsi, %r8
imulq %r15, %r8
addq %rdx, %r8
movq %rsi, %xmm9
punpckldq %xmm3, %xmm9    # xmm9 = xmm9[0],xmm3[0],xmm9[1],xmm3[1]
subpd %xmm4, %xmm9
movapd %xmm9, %xmm10
unpckhpd %xmm9, %xmm10           # xmm10 = xmm10[1],xmm9[1]
addsd %xmm9, %xmm10
movq (%rbp,%rdi,8), %xmm9
punpckldq %xmm3, %xmm9    # xmm9 = xmm9[0],xmm3[0],xmm9[1],xmm3[1]
subpd %xmm4, %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 (%r12,%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 0x18d39
movq 0x8(%rsp), %rax
movq (%rax,%rdi,8), %rax
movq %rax, (%rbx,%r8,8)
incq %rsi
cmpq %r13, %rsi
jne 0x18c6b
movq 0x20(%rsp), %rdx
incq %rdx
cmpq 0x10(%rsp), %rdx
jne 0x18a65
movq %r14, %rdi
callq 0x9580
movq %rbp, %rdi
callq 0x9580
movq %r12, %rdi
callq 0x9580
movq 0x8(%rsp), %rdi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x9580