// File: tomfunkhouser[P]gaps/pkgs/RNBasics/RNSvd.cpp
// Function: gaps::bidiagonalize(double const*, int, int, double*, double*, double*)
void bidiagonalize(const RNScalar *a,int m,int n,RNScalar *u,RNScalar *b,RNScalar *v)
{
    int i,j, min=MIN(m,n);
    RNScalar *usave = u, *vsave = v, *h = ALLOC1D(MAX(m,n));

    /* we need square matrices to accumulate the transformations */
    if (min != m) u = ALLOC2D(m,m);
    if (min != n) v = ALLOC2D(n,n);

    /* start off with u and v equal to the identity, and b equal to a */
    CLEAR2D(u,m,m);
    CLEAR2D(v,n,n);
    for (i=0; i<m; i++) REF2D(u,m,m,i,i) = 1;
    for (i=0; i<n; i++) REF2D(v,n,n,i,i) = 1;
    if (b != a) COPY2D(b,m,n,a);

    /* walk down the diagonal */
    for (i = 0; i<min; i++) {
	/* zero the entries below b[i,i] */
	householder_zero_col(b,u,i,i,m,n,h);
	/* zero the entries to the right of b[i,i+1] */
	householder_zero_row(b,v,i,i+1,m,n,h);
    }
    /* when m < n (matrix wider than tall), the above
       leaves a non-0 element in the [m-1,m]th spot.
       This is the bottom superdiagonal element of an (m+1)x(m+1);
       use the clear routine to get rid of it. */
    if (min != n)
	clr_bot_supdiag_elt(b,0,min,v,m,n,n);

    /* For non-square arrays, lop off the parts we don't need */
    if (min!=m) {
	for (i=0; i<m; i++) for (j=0; j<min; j++)
	    REF2D(usave,m,min,i,j)=REF2D(u,m,m,i,j);
	FREE(u);
    }
    if (min!=n) {
	for (i=0; i<n; i++) for (j=0; j<min; j++)
	    REF2D(vsave,min,n,j,i)=REF2D(v,n,n,j,i);
	FREE(v);
    }
    FREE(h);
}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x60(%rsp)
movl %esi, 0x5c(%rsp)
movl %edx, 0x58(%rsp)
movq %rcx, 0x50(%rsp)
movq %r8, 0x48(%rsp)
movq %r9, 0x40(%rsp)
movl 0x5c(%rsp), %eax
cmpl 0x58(%rsp), %eax
jge 0xd36f4
movl 0x5c(%rsp), %eax
movl %eax, 0x14(%rsp)
jmp 0xd36fc
movl 0x58(%rsp), %eax
movl %eax, 0x14(%rsp)
movl 0x14(%rsp), %eax
movl %eax, 0x34(%rsp)
movq 0x50(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x40(%rsp), %rax
movq %rax, 0x20(%rsp)
movl 0x5c(%rsp), %eax
cmpl 0x58(%rsp), %eax
jle 0xd372c
movl 0x5c(%rsp), %eax
movl %eax, 0x10(%rsp)
jmp 0xd3734
movl 0x58(%rsp), %eax
movl %eax, 0x10(%rsp)
movl 0x10(%rsp), %eax
movl %eax, %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0xf6a0
movq %rax, 0x18(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x5c(%rsp), %eax
je 0xd376f
movl 0x5c(%rsp), %eax
imull 0x5c(%rsp), %eax
movl %eax, %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0xf6a0
movq %rax, 0x50(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x58(%rsp), %eax
je 0xd3794
movl 0x58(%rsp), %eax
imull 0x58(%rsp), %eax
movl %eax, %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0xf6a0
movq %rax, 0x40(%rsp)
movq 0x50(%rsp), %rdi
movl 0x5c(%rsp), %eax
imull 0x5c(%rsp), %eax
movslq %eax, %rdx
shlq $0x3, %rdx
xorl %esi, %esi
callq 0xf280
movq 0x40(%rsp), %rdi
movl 0x58(%rsp), %eax
imull 0x58(%rsp), %eax
movslq %eax, %rdx
shlq $0x3, %rdx
xorl %esi, %esi
callq 0xf280
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
cmpl 0x5c(%rsp), %eax
jge 0xd380d
movq 0x50(%rsp), %rax
movl 0x5c(%rsp), %ecx
imull 0x3c(%rsp), %ecx
addl 0x3c(%rsp), %ecx
movslq %ecx, %rcx
movsd 0x5f80d(%rip), %xmm0    # 0x133008
movsd %xmm0, (%rax,%rcx,8)
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0xd37d4
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
cmpl 0x58(%rsp), %eax
jge 0xd384e
movq 0x40(%rsp), %rax
movl 0x58(%rsp), %ecx
imull 0x3c(%rsp), %ecx
addl 0x3c(%rsp), %ecx
movslq %ecx, %rcx
movsd 0x5f7cc(%rip), %xmm0    # 0x133008
movsd %xmm0, (%rax,%rcx,8)
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0xd3815
movq 0x48(%rsp), %rax
cmpq 0x60(%rsp), %rax
je 0xd387b
movq 0x48(%rsp), %rdi
movq 0x60(%rsp), %rsi
movl 0x5c(%rsp), %eax
imull 0x58(%rsp), %eax
cltq
shlq $0x3, %rax
movslq %eax, %rdx
callq 0xf3d0
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
cmpl 0x34(%rsp), %eax
jge 0xd38f1
movq 0x48(%rsp), %rdi
movq 0x50(%rsp), %rsi
movl 0x3c(%rsp), %edx
movl 0x3c(%rsp), %ecx
movl 0x5c(%rsp), %r8d
movl 0x58(%rsp), %r9d
movq 0x18(%rsp), %rax
movq %rax, (%rsp)
callq 0xd2180
movq 0x48(%rsp), %rdi
movq 0x40(%rsp), %rsi
movl 0x3c(%rsp), %edx
movl 0x3c(%rsp), %ecx
addl $0x1, %ecx
movl 0x5c(%rsp), %r8d
movl 0x58(%rsp), %r9d
movq 0x18(%rsp), %rax
movq %rax, (%rsp)
callq 0xd25e0
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0xd3883
movl 0x34(%rsp), %eax
cmpl 0x58(%rsp), %eax
je 0xd3921
movq 0x48(%rsp), %rdi
movl 0x34(%rsp), %edx
movq 0x40(%rsp), %rcx
movl 0x5c(%rsp), %r8d
movl 0x58(%rsp), %r9d
movl 0x58(%rsp), %eax
xorl %esi, %esi
movl %eax, (%rsp)
callq 0xd2e50
movl 0x34(%rsp), %eax
cmpl 0x5c(%rsp), %eax
je 0xd39a9
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
cmpl 0x5c(%rsp), %eax
jge 0xd399f
movl $0x0, 0x38(%rsp)
movl 0x38(%rsp), %eax
cmpl 0x34(%rsp), %eax
jge 0xd3990
movq 0x50(%rsp), %rax
movl 0x5c(%rsp), %ecx
imull 0x3c(%rsp), %ecx
addl 0x38(%rsp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x28(%rsp), %rax
movl 0x34(%rsp), %ecx
imull 0x3c(%rsp), %ecx
addl 0x38(%rsp), %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0xd3945
jmp 0xd3992
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0xd3933
movq 0x50(%rsp), %rdi
callq 0xf5f0
movl 0x34(%rsp), %eax
cmpl 0x58(%rsp), %eax
je 0xd3a31
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
cmpl 0x58(%rsp), %eax
jge 0xd3a27
movl $0x0, 0x38(%rsp)
movl 0x38(%rsp), %eax
cmpl 0x34(%rsp), %eax
jge 0xd3a18
movq 0x40(%rsp), %rax
movl 0x58(%rsp), %ecx
imull 0x38(%rsp), %ecx
addl 0x3c(%rsp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x20(%rsp), %rax
movl 0x58(%rsp), %ecx
imull 0x38(%rsp), %ecx
addl 0x3c(%rsp), %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0xd39cd
jmp 0xd3a1a
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0xd39bb
movq 0x40(%rsp), %rdi
callq 0xf5f0
movq 0x18(%rsp), %rdi
callq 0xf5f0
addq $0x68, %rsp
retq