// File: manikandan5[P]Image-Matching-Stitching-Warping/siftpp/sift.cpp
// Function: VL::Sift::getKeypoint(float, float, float) const
Sift::Keypoint
Sift::getKeypoint(VL::float_t x, VL::float_t y, VL::float_t sigma) const
{

  /*
    The formula linking the keypoint scale sigma to the octave and
    scale index is

    (1) sigma(o,s) = sigma0 2^(o+s/S)

    for which
    
    (2) o + s/S = log2 sigma/sigma0 == phi.

    In addition to the scale index s (which can be fractional due to
    scale interpolation) a keypoint has an integer scale index is too
    (which is the index of the scale level where it was detected in
    the DoG scale space). We have the constraints:
 
    - o and is are integer

    - is is in the range [smin+1, smax-2  ]

    - o  is in the range [omin,   omin+O-1]

    - is = rand(s) most of the times (but not always, due to the way s
      is obtained by quadratic interpolation of the DoG scale space).

    Depending on the values of smin and smax, often (2) has multiple
    solutions is,o that satisfy all constraints.  In this case we
    choose the one with biggest index o (this saves a bit of
    computation).

    DETERMINING THE OCTAVE INDEX O

    From (2) we have o = phi - s/S and we want to pick the biggest
    possible index o in the feasible range. This corresponds to
    selecting the smallest possible index s. We write s = is + ds
    where in most cases |ds|<.5 (but in general |ds|<1). So we have

       o = phi - s/S,   s = is + ds ,   |ds| < .5 (or |ds| < 1).

    Since is is in the range [smin+1,smax-2], s is in the range
    [smin+.5,smax-1.5] (or [smin,smax-1]), the number o is an integer
    in the range phi+[-smax+1.5,-smin-.5] (or
    phi+[-smax+1,-smin]). Thus the maximum value of o is obtained for
    o = floor(phi-smin-.5) (or o = floor(phi-smin)).

    Finally o is clamped to make sure it is contained in the feasible
    range.

    DETERMINING THE SCALE INDEXES S AND IS

    Given o we can derive is by writing (2) as

      s = is + ds = S(phi - o).

    We then take is = round(s) and clamp its value to be in the
    feasible range.
  */

  int o,ix,iy,is ;
  VL::float_t s,phi ;

  phi = log2(sigma/sigma0) ;
  o   = fast_floor( phi -  (VL::float_t(smin)+.5)/S ) ;
  o   = std::min(o, omin+O-1) ;
  o   = std::max(o, omin    ) ;
  s   = S * (phi - o) ;

  is  = int(s + 0.5) ;
  is  = std::min(is, smax - 2) ;
  is  = std::max(is, smin + 1) ;
  
  VL::float_t per = getOctaveSamplingPeriod(o) ;
  ix = int(x / per + 0.5) ;
  iy = int(y / per + 0.5) ;
  
  Keypoint key ;
  key.o  = o ;

  key.ix = ix ;
  key.iy = iy ;
  key.is = is ;

  key.x = x ;
  key.y = y ;
  key.s = s ;
  
  key.sigma = sigma ;
  
  return key ;
}

// Assembly:
subq $0x58, %rsp
movq %rdi, 0x8(%rsp)
movq %rdi, 0x10(%rsp)
movq %rsi, 0x50(%rsp)
movss %xmm0, 0x4c(%rsp)
movss %xmm1, 0x48(%rsp)
movss %xmm2, 0x44(%rsp)
movq 0x50(%rsp), %rax
movq %rax, (%rsp)
movss 0x44(%rsp), %xmm0
divss 0x4(%rax), %xmm0
cvtss2sd %xmm0, %xmm0
callq 0x59a0
movq (%rsp), %rax
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x2c(%rsp)
movss 0x2c(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
cvtsi2ssl 0x18(%rax), %xmm1
cvtss2sd %xmm1, %xmm1
movsd 0x60dd(%rip), %xmm2     # 0xc8048
addsd %xmm2, %xmm1
cvtsi2sdl 0x10(%rax), %xmm2
divsd %xmm2, %xmm1
subsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
callq 0xc5cc0
movq (%rsp), %rcx
movl %eax, 0x40(%rsp)
movl 0x14(%rcx), %eax
addl 0xc(%rcx), %eax
subl $0x1, %eax
movl %eax, 0x28(%rsp)
leaq 0x40(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x93c90
movq (%rsp), %rsi
movl (%rax), %eax
movl %eax, 0x40(%rsp)
addq $0x14, %rsi
leaq 0x40(%rsp), %rdi
callq 0x93c30
movq %rax, %rcx
movq (%rsp), %rax
movl (%rcx), %ecx
movl %ecx, 0x40(%rsp)
cvtsi2ssl 0x10(%rax), %xmm0
movss 0x2c(%rsp), %xmm1
cvtsi2ssl 0x40(%rsp), %xmm2
subss %xmm2, %xmm1
mulss %xmm1, %xmm0
movss %xmm0, 0x30(%rsp)
movss 0x30(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x6049(%rip), %xmm1     # 0xc8048
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
movl %ecx, 0x34(%rsp)
movl 0x1c(%rax), %eax
subl $0x2, %eax
movl %eax, 0x24(%rsp)
leaq 0x34(%rsp), %rdi
leaq 0x24(%rsp), %rsi
callq 0x93c90
movq %rax, %rcx
movq (%rsp), %rax
movl (%rcx), %ecx
movl %ecx, 0x34(%rsp)
movl 0x18(%rax), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
leaq 0x34(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x93c30
movq (%rsp), %rdi
movl (%rax), %eax
movl %eax, 0x34(%rsp)
movl 0x40(%rsp), %esi
callq 0xc5ce0
movq 0x8(%rsp), %rdi
movq 0x10(%rsp), %rax
movss %xmm0, 0x1c(%rsp)
movss 0x4c(%rsp), %xmm0
divss 0x1c(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x5fc3(%rip), %xmm1     # 0xc8048
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
movl %ecx, 0x3c(%rsp)
movss 0x48(%rsp), %xmm0
divss 0x1c(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x5f9f(%rip), %xmm1     # 0xc8048
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
movl %ecx, 0x38(%rsp)
movl 0x40(%rsp), %ecx
movl %ecx, (%rdi)
movl 0x3c(%rsp), %ecx
movl %ecx, 0x4(%rdi)
movl 0x38(%rsp), %ecx
movl %ecx, 0x8(%rdi)
movl 0x34(%rsp), %ecx
movl %ecx, 0xc(%rdi)
movss 0x4c(%rsp), %xmm0
movss %xmm0, 0x10(%rdi)
movss 0x48(%rsp), %xmm0
movss %xmm0, 0x14(%rdi)
movss 0x30(%rsp), %xmm0
movss %xmm0, 0x18(%rdi)
movss 0x44(%rsp), %xmm0
movss %xmm0, 0x1c(%rdi)
addq $0x58, %rsp
retq
nopw %cs:(%rax,%rax)