// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/RNBasics/RNSvd.cpp
// Function: gaps::golub_kahn_svd_rot(double*, int, int, double*, int, int, int)
void golub_kahn_svd_rot(RNScalar * b,int p,int q,RNScalar * v,int m,int n,int min)
{
    RNScalar t11, t12, t22;
    RNScalar uu;
    RNScalar b11, b12;
    RNScalar dm,fm,dn,fn;
    RNScalar hypot,cos,sin;
    RNScalar d, s, y, z;

    /* grab the last diagonal and superdiagonal elements of b22 */
    fm = (q-2) < 0 ? 0 : REF2D(b,m,n,q-2,q-1);
    dm = REF2D(b,m,n,q-1,q-1);	fn = REF2D(b,m,n,q-1,q);
				dn = REF2D(b,m,n,q,q);

    /* create the trailing 2x2 submatrix of T = b22^t b22 */
    t11 = dm*dm + fm * fm;
    t12 = dm * fn;		t22 = dn * dn + fn * fn;

    /* find the eigenvalues of the T matrix.
    **
    ** The quadratic equation for the eigenvalues has coefficients:
    ** a = 1
    ** b = -(t11+t22)
    ** c = t11 t22 - t12 t12
    **
    ** b^2 - 4ac = (t11^2 + t22^2 + 2 t11 t12) - 4 t11 t22 + 4 t12 t12
    **           = (t11 - t22)^2 + 4 t12 t12
    **
    ** sqrt(b^2-4ac) = sqrt((t11 - t22)^2 + 4 t12 t12) -- use "pythag()"
    **
    ** using quadratic formula, we have the eigenvalues:
    ** (u1,u2) = .5 (t11 + t22 +/- pythag(...))
    **         = t22 + .5 (t11 - t22 +/- pythag(...))
    **
    ** We propogate the .5 into the pythag term, yielding golub's equation 8.2-2
    ** for the "wilkinson shift".
    ** [Note:  Golub says to use (t22 + d - signum(d) s) to find the eigenvalue
    ** closer to t22.  He's right.  ]
    **/
    d = ((RNScalar) 0.5)*(t11 - t22);
    s = fhypot (d,t12);
    uu = t22 + d + ((d > 0) ? -s : s);

    /* grab the leading 2x1 of b */
    b11 = REF2D(b,m,n,p,p);	b12 = REF2D(b,m,n,p,p+1);

    /* make the leading 2x1 submatrix of T */
    t11 = b11 * b11;
    t12 = b11 * b12;

    /* calculate the rotation that would zero the off-diagonal term of the
    ** shifted matrix T - uu I
    */
    y = t11 - uu;
    z = t12;
    hypot = fhypot (y,z);
    cos = y / hypot;
    sin = z / hypot;

    /* perform the rotation on B.  This sprays some glop into the upper-left
    ** subdiagonal element.
    */
    rotate_cols(p,p+1,cos,sin,b,p,2,m,n);
    /* accumulate the rotation into the rows of v */
    rotate_rows(p,p+1,cos,sin,v,0,n,min,n);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x18, %rsp
movl %r9d, %ebx
movq %rcx, %r14
movl %esi, %r15d
movq %rdi, %rax
cmpl $0x1, %edx
jg 0x67156
leal -0x1(%rdx), %ecx
xorpd %xmm1, %xmm1
jmp 0x6716b
leal -0x2(%rdx), %esi
imull %ebx, %esi
leal -0x1(%rdx), %ecx
addl %edx, %esi
decl %esi
movslq %esi, %rsi
movsd (%rax,%rsi,8), %xmm1
movl %ecx, %esi
imull %ebx, %esi
addl %esi, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
addl %edx, %esi
movslq %esi, %rcx
movsd (%rax,%rcx,8), %xmm3
leal 0x1(%rbx), %ecx
imull %edx, %ecx
movslq %ecx, %rcx
movapd %xmm0, %xmm2
mulsd %xmm3, %xmm2
unpcklpd %xmm3, %xmm1            # xmm1 = xmm1[0],xmm3[0]
movhpd (%rax,%rcx,8), %xmm0    # xmm0 = xmm0[0],mem[0]
mulpd %xmm1, %xmm1
mulpd %xmm0, %xmm0
addpd %xmm1, %xmm0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
subsd %xmm1, %xmm0
mulsd 0x2be52(%rip), %xmm0    # 0x93010
mulsd %xmm2, %xmm2
addsd %xmm0, %xmm1
xorpd %xmm3, %xmm3
cmpltsd %xmm0, %xmm3
mulsd %xmm0, %xmm0
addsd %xmm2, %xmm0
sqrtsd %xmm0, %xmm0
movapd 0x2be4d(%rip), %xmm2    # 0x93030
xorpd %xmm0, %xmm2
movapd %xmm3, %xmm4
andnpd %xmm0, %xmm4
andpd %xmm2, %xmm3
orpd %xmm4, %xmm3
addsd %xmm1, %xmm3
movl %ebx, %ecx
imull %r15d, %ecx
leal (%rcx,%r15), %edx
movslq %edx, %rdx
movsd (%rax,%rdx,8), %xmm1
leal 0x1(%r15), %ebp
leal 0x1(%rcx,%r15), %ecx
movslq %ecx, %rcx
movapd %xmm1, %xmm2
mulsd %xmm1, %xmm2
subsd %xmm3, %xmm2
mulsd (%rax,%rcx,8), %xmm1
movapd %xmm1, %xmm0
movapd %xmm1, %xmm3
mulsd %xmm1, %xmm0
movapd %xmm2, %xmm1
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
sqrtsd %xmm1, %xmm0
divsd %xmm0, %xmm2
movsd %xmm2, 0x8(%rsp)
movapd %xmm3, %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, 0x10(%rsp)
movl %ebx, (%rsp)
pushq $0x2
popq %r8
movl %r15d, %edi
movl %ebp, %esi
movapd %xmm2, %xmm0
movq %rax, %rdx
movl %r15d, %ecx
callq 0x66b9e
movl %ebx, (%rsp)
movl %r15d, %edi
movl %ebp, %esi
movsd 0x8(%rsp), %xmm0
movsd 0x10(%rsp), %xmm1
movq %r14, %rdx
xorl %ecx, %ecx
movl %ebx, %r8d
callq 0x66c0f
addq $0x18, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq