// File: tomfunkhouser[P]gaps/pkgs/RNBasics/RNSvd.cpp
// Function: gaps::RNSvdDecompose(int, int, double const*, double*, double*, double*)
void RNSvdDecompose(int m, int n, 
    const RNScalar *a,
    RNScalar *u, RNScalar *w, RNScalar *vt)
{
    int i, j, k, min = MIN(m,n);
    RNScalar *g, *p, wi;

    g = ALLOC2D(m,n);
    bidiagonalize(a,m,n,u,g,vt);


    bidiagonal_svd(g,m,n,u,vt);
    for (i=0; i<min; i++) w[i] = REF2D(g,m,n,i,i);

    /* insertion sort singular values.  Note that since
    ** the svd algorithm produces values sorted or nearly sorted,
    ** an insertion sort is efficient.
    */
    for (i=1; i<min; i++) {
	if (w[i] > w[i-1]) {
	    /* save w[i], and col i of u and row i of vt.  use "g" as buffer */
	    wi = w[i];
	    p=g;
	    for (k=0; k<m; k++) *p++ = REF2D(u,m,min,k,i);
	    for (k=0; k<n; k++) *p++ = REF2D(vt,min,n,i,k);
	    /* slide columns over */
	    for (j=i; j>0 && wi > w[j-1]; j--) {
		w[j] = w[j-1];
		for (k=0; k<m; k++) REF2D(u,m,min,k,j)=REF2D(u,m,min,k,j-1);
		for (k=0; k<n; k++) REF2D(vt,min,n,j,k)=REF2D(vt,min,n,j-1,k);
	    }
	    /* put original i stuff where we ended up */
	    w[j] = wi;
	    p=g;
	    for (k=0; k<m; k++) REF2D(u,m,min,k,j) = *p++;
	    for (k=0; k<n; k++) REF2D(vt,min,n,j,k) = *p++;
	}
    }
	    
    FREE(g);
}

// Assembly:
subq $0x58, %rsp
movl %edi, 0x54(%rsp)
movl %esi, 0x50(%rsp)
movq %rdx, 0x48(%rsp)
movq %rcx, 0x40(%rsp)
movq %r8, 0x38(%rsp)
movq %r9, 0x30(%rsp)
movl 0x54(%rsp), %eax
cmpl 0x50(%rsp), %eax
jge 0xd3df4
movl 0x54(%rsp), %eax
movl %eax, 0x4(%rsp)
jmp 0xd3dfc
movl 0x50(%rsp), %eax
movl %eax, 0x4(%rsp)
movl 0x4(%rsp), %eax
movl %eax, 0x20(%rsp)
movl 0x54(%rsp), %eax
imull 0x50(%rsp), %eax
movl %eax, %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0xf6a0
movq %rax, 0x18(%rsp)
movq 0x48(%rsp), %rdi
movl 0x54(%rsp), %esi
movl 0x50(%rsp), %edx
movq 0x40(%rsp), %rcx
movq 0x18(%rsp), %r8
movq 0x30(%rsp), %r9
callq 0xd36c0
movq 0x18(%rsp), %rdi
movl 0x54(%rsp), %esi
movl 0x50(%rsp), %edx
movq 0x40(%rsp), %rcx
movq 0x30(%rsp), %r8
callq 0xd3a40
movl $0x0, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
cmpl 0x20(%rsp), %eax
jge 0xd3ea4
movq 0x18(%rsp), %rax
movl 0x50(%rsp), %ecx
imull 0x2c(%rsp), %ecx
addl 0x2c(%rsp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x38(%rsp), %rax
movslq 0x2c(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0xd3e64
movl $0x1, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
cmpl 0x20(%rsp), %eax
jge 0xd4195
movq 0x38(%rsp), %rax
movslq 0x2c(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x38(%rsp), %rax
movl 0x2c(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
ucomisd (%rax,%rcx,8), %xmm0
jbe 0xd4183
movq 0x38(%rsp), %rax
movslq 0x2c(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, 0x8(%rsp)
movq 0x18(%rsp), %rax
movq %rax, 0x10(%rsp)
movl $0x0, 0x24(%rsp)
movl 0x24(%rsp), %eax
cmpl 0x54(%rsp), %eax
jge 0xd3f50
movq 0x40(%rsp), %rax
movl 0x20(%rsp), %ecx
imull 0x24(%rsp), %ecx
addl 0x2c(%rsp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x10(%rsp), %rax
movq %rax, %rcx
addq $0x8, %rcx
movq %rcx, 0x10(%rsp)
movsd %xmm0, (%rax)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0xd3f0a
movl $0x0, 0x24(%rsp)
movl 0x24(%rsp), %eax
cmpl 0x50(%rsp), %eax
jge 0xd3f9e
movq 0x30(%rsp), %rax
movl 0x50(%rsp), %ecx
imull 0x2c(%rsp), %ecx
addl 0x24(%rsp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x10(%rsp), %rax
movq %rax, %rcx
addq $0x8, %rcx
movq %rcx, 0x10(%rsp)
movsd %xmm0, (%rax)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0xd3f58
movl 0x2c(%rsp), %eax
movl %eax, 0x28(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x28(%rsp)
movb %al, 0x3(%rsp)
jle 0xd3fd4
movsd 0x8(%rsp), %xmm0
movq 0x38(%rsp), %rax
movl 0x28(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
ucomisd (%rax,%rcx,8), %xmm0
seta %al
movb %al, 0x3(%rsp)
movb 0x3(%rsp), %al
testb $0x1, %al
jne 0xd3fe1
jmp 0xd40c6
movq 0x38(%rsp), %rax
movl 0x28(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x38(%rsp), %rax
movslq 0x28(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl $0x0, 0x24(%rsp)
movl 0x24(%rsp), %eax
cmpl 0x54(%rsp), %eax
jge 0xd405c
movq 0x40(%rsp), %rax
movl 0x20(%rsp), %ecx
imull 0x24(%rsp), %ecx
movl 0x28(%rsp), %edx
subl $0x1, %edx
addl %edx, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x40(%rsp), %rax
movl 0x20(%rsp), %ecx
imull 0x24(%rsp), %ecx
addl 0x28(%rsp), %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0xd400c
movl $0x0, 0x24(%rsp)
movl 0x24(%rsp), %eax
cmpl 0x50(%rsp), %eax
jge 0xd40b4
movq 0x30(%rsp), %rax
movl 0x50(%rsp), %ecx
movl 0x28(%rsp), %edx
subl $0x1, %edx
imull %edx, %ecx
addl 0x24(%rsp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x30(%rsp), %rax
movl 0x50(%rsp), %ecx
imull 0x28(%rsp), %ecx
addl 0x24(%rsp), %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0xd4064
jmp 0xd40b6
movl 0x28(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x28(%rsp)
jmp 0xd3fa6
movsd 0x8(%rsp), %xmm0
movq 0x38(%rsp), %rax
movslq 0x28(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq 0x18(%rsp), %rax
movq %rax, 0x10(%rsp)
movl $0x0, 0x24(%rsp)
movl 0x24(%rsp), %eax
cmpl 0x54(%rsp), %eax
jge 0xd4133
movq 0x10(%rsp), %rax
movq %rax, %rcx
addq $0x8, %rcx
movq %rcx, 0x10(%rsp)
movsd (%rax), %xmm0
movq 0x40(%rsp), %rax
movl 0x20(%rsp), %ecx
imull 0x24(%rsp), %ecx
addl 0x28(%rsp), %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0xd40ed
movl $0x0, 0x24(%rsp)
movl 0x24(%rsp), %eax
cmpl 0x50(%rsp), %eax
jge 0xd4181
movq 0x10(%rsp), %rax
movq %rax, %rcx
addq $0x8, %rcx
movq %rcx, 0x10(%rsp)
movsd (%rax), %xmm0
movq 0x30(%rsp), %rax
movl 0x50(%rsp), %ecx
imull 0x28(%rsp), %ecx
addl 0x24(%rsp), %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0xd413b
jmp 0xd4183
jmp 0xd4185
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0xd3eac
movq 0x18(%rsp), %rdi
callq 0xf5f0
addq $0x58, %rsp
retq
nopw %cs:(%rax,%rax)