// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/RNBasics/RNSvd.cpp
// Function: gaps::householder_zero_col(double*, double*, int, int, int, int, double*)
void householder_zero_col(RNScalar *a,RNScalar *u,int i,int j,int m,int n,RNScalar *hv)
	/* hv is a work vector, length m */
{
    RNScalar	scale,	/* a scale factor for X1 */
		sigma,		/* the norm^2 of X1 */
		snorm,		/* +/- the norm of X1 */
		f, h, s, dot;
    int k,l;

    /* we will scale X1 by its l1-norm.  squawk! */
    for (scale=0, k=i; k<m; k++) scale += ((RNScalar) fabs(REF2D(a,m,n,k,j)));

    /* if X1 is 0, no point doing anything else */
    if (!scale) return;

    /* divide out the l1-norm, and calculate sigma = |X|^2 */
    for (k=i; k<m; k++) hv[k] = REF2D(a,m,n,k,j) / scale;
    for (sigma=0, k=i; k<m; k++) sigma += hv[k]*hv[k];

    /* The householder vector is X1 +/- (|X1|,0,0,...).  We will
    ** contruct this vector in hv and use it to perform the householder
    ** transformation on the matrix.  The plus or minus on the norm
    ** is to reduce roundoff error.  */
    f = hv[i];
    snorm = ((RNScalar) ((f > 0) ? -sqrt(sigma) : sqrt(sigma)));
    h = f*snorm - sigma;	/* eqn 11.2.4 in Press et.al. */
    hv[i] = f - snorm;

    /* set the first column of a to be the (|X1|,0,...) -- this is
    ** what we would get by performing the transformation, but this
    ** way's faster */
    REF2D(a,m,n,i,j) = scale * snorm;
    for (k=i+1; k<m; k++) REF2D(a,m,n,k,j) = 0;

    /* Now perform the householder transformation on the rest of
    ** the columns.  If the householder vector is X, and -half its norm^2
    ** is h, the householder transform is P_ij : delta_ij + x_i x_j / h.
    ** We don't actually create the P matrix, we just do the calcuation.
    */
    for (k=j+1; k<n; k++) {
	for (dot=0, l=i; l<m; l++) dot += REF2D(a,m,n,l,k)*hv[l];
	s = dot/h;
	for (l=i; l<m; l++) REF2D(a,m,n,l,k) += s*hv[l];
    }

    /* Similarly, perform the householder transformation on (all)
    ** the rows of u.  Note that it's the rows of u rather than
    ** the columns, because we want U to invert what we've done to a.
    */
    for (k=0; k<m; k++) {
	for (dot=0, l=i; l<m; l++) dot += REF2D(u,m,m,k,l)*hv[l];
	s = dot/h;
	for (l=i; l<m; l++) REF2D(u,m,m,k,l) += s*hv[l];
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rsi, %rbx
movq 0x90(%rsp), %r15
movslq %edx, %r12
movslq %r8d, %r13
movslq %r9d, %rsi
movslq %ecx, %r14
movq %rsi, %rax
imulq %r12, %rax
leaq (,%r14,8), %r9
leaq (%r9,%rax,8), %rdx
leaq (%rdi,%rdx), %rax
leaq (,%rsi,8), %rbp
xorpd %xmm4, %xmm4
movapd 0x2cb5f(%rip), %xmm0    # 0x93270
movq %r12, %r8
cmpq %r13, %r8
jge 0x6672d
movsd (%rax), %xmm1
andpd %xmm0, %xmm1
addsd %xmm1, %xmm4
incq %r8
addq %rbp, %rax
jmp 0x66714
xorpd %xmm0, %xmm0
ucomisd %xmm0, %xmm4
jne 0x6673d
jnp 0x66933
leaq (%rdi,%rdx), %rax
movq %r12, %r8
cmpq %r13, %r8
jge 0x6675f
movsd (%rax), %xmm0
divsd %xmm4, %xmm0
movsd %xmm0, (%r15,%r8,8)
incq %r8
addq %rbp, %rax
jmp 0x66744
xorpd %xmm5, %xmm5
movq %r12, %rax
cmpq %r13, %rax
jge 0x6677e
movsd (%r15,%rax,8), %xmm0
mulsd %xmm0, %xmm0
addsd %xmm0, %xmm5
incq %rax
jmp 0x66766
movsd (%r15,%r12,8), %xmm3
xorpd %xmm6, %xmm6
ucomisd %xmm6, %xmm5
jb 0x66794
sqrtsd %xmm5, %xmm0
jmp 0x667f5
movapd %xmm5, %xmm0
movq %rsi, 0x38(%rsp)
movsd %xmm3, 0x30(%rsp)
movq %rdi, 0x28(%rsp)
movq %rdx, 0x20(%rsp)
movl %ecx, 0xc(%rsp)
movq %r9, 0x18(%rsp)
movsd %xmm4, 0x10(%rsp)
movapd %xmm5, 0x40(%rsp)
callq 0xe350
xorpd %xmm6, %xmm6
movapd 0x40(%rsp), %xmm5
movsd 0x10(%rsp), %xmm4
movq 0x18(%rsp), %r9
movl 0xc(%rsp), %ecx
movq 0x20(%rsp), %rdx
movq 0x28(%rsp), %rdi
movsd 0x30(%rsp), %xmm3
movq 0x38(%rsp), %rsi
movapd 0x2c833(%rip), %xmm1    # 0x93030
movapd %xmm0, %xmm2
xorpd %xmm1, %xmm2
cmpltsd %xmm3, %xmm6
andpd %xmm6, %xmm2
andnpd %xmm0, %xmm6
orpd %xmm2, %xmm6
xorpd %xmm1, %xmm5
movapd %xmm3, %xmm0
subsd %xmm6, %xmm0
movsd %xmm0, (%r15,%r12,8)
mulsd %xmm6, %xmm4
movl %esi, %eax
imull %r12d, %eax
addl %ecx, %eax
cltq
movsd %xmm4, (%rdi,%rax,8)
leaq 0x1(%r12), %rax
movq %rax, %rcx
imulq %rsi, %rcx
leaq (%r9,%rcx,8), %rcx
addq %rdi, %rcx
cmpq %r13, %rax
jge 0x6685f
andq $0x0, (%rcx)
incq %rax
addq %rbp, %rcx
jmp 0x6684e
mulsd %xmm6, %xmm3
addsd %xmm5, %xmm3
leaq (%rdi,%rdx), %rax
addq $0x8, %rax
incq %r14
cmpq %rsi, %r14
jge 0x668cb
xorpd %xmm0, %xmm0
movq %rax, %rcx
movq %r12, %rdx
cmpq %r13, %rdx
jge 0x6689c
movsd (%rcx), %xmm1
mulsd (%r15,%rdx,8), %xmm1
addsd %xmm1, %xmm0
incq %rdx
addq %rbp, %rcx
jmp 0x66881
divsd %xmm3, %xmm0
movq %rax, %rcx
movq %r12, %rdx
cmpq %r13, %rdx
jge 0x668c5
movsd (%r15,%rdx,8), %xmm1
mulsd %xmm0, %xmm1
addsd (%rcx), %xmm1
movsd %xmm1, (%rcx)
incq %rdx
addq %rbp, %rcx
jmp 0x668a6
addq $0x8, %rax
jmp 0x6686f
xorl %eax, %eax
testl %r13d, %r13d
movl $0x0, %ecx
cmovgl %r13d, %ecx
leaq (,%r13,8), %rdx
cmpq %rcx, %rax
je 0x66933
xorpd %xmm0, %xmm0
movq %r12, %rsi
cmpq %r13, %rsi
jge 0x66906
movsd (%rbx,%rsi,8), %xmm1
mulsd (%r15,%rsi,8), %xmm1
addsd %xmm1, %xmm0
incq %rsi
jmp 0x668ed
divsd %xmm3, %xmm0
movq %r12, %rsi
cmpq %r13, %rsi
jge 0x6692b
movsd (%r15,%rsi,8), %xmm1
mulsd %xmm0, %xmm1
addsd (%rbx,%rsi,8), %xmm1
movsd %xmm1, (%rbx,%rsi,8)
incq %rsi
jmp 0x6690d
incq %rax
addq %rdx, %rbx
jmp 0x668e1
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq