//Swap rows in a col major array void swapRows(int rows, int cols, double * array, int rowA, int rowB) { double * tempRow = Calloc(cols, double); copyVect(cols, array+rowA, rows, tempRow, 1); copyVect(cols, array+rowB, rows, array+rowA, rows); copyVect(cols, tempRow, 1, array+rowB, rows); Free(tempRow); }
/* Algorithm taken from Matrix Algorithms Vol. II by G.W. Stewart. His original pseudocode is in the comments. This function takes a vector a and produces a u that generates the Householder transformation H = I - uuH such that Ha = ve1. n is the length of the vectors. */ void housegen(Complex *a, Complex *u, Complex *v, int n) { int i; Real tmp; Complex rho; //u = a copyVect(a,u,n); //v = ||a||2 v->real = norm(a,n); v->imag = 0.0;//must be done after norm is taken above! //if(v = 0)u[1] = sqrt(2); return; fi <-no clue what 'fi' is if(v->real == 0.0)//v can only be real right now should i be using epsilon? { u[0].real = sqrt(2); u[0].imag = 0; return; } //if(u[1] != 0) if(u[0].real != 0.0 || u[0].imag != 0.0)// not sure if I should use an epsilon here? { //rho = u_bar[1]/|u[1]| tmp = ABS(u[0]); rho.real = u[0].real/tmp; rho.imag = -u[0].imag/tmp; } else//else rho = 1; { rho.real = 1.0; rho.imag = 0.0; } //u = (rho/v)*u for(i = 0; i < n; i++) { //v can still only be real at this point u[i] = complexMult(rho, u[i]); u[i].real /= v->real; u[i].imag /= v->real; } //u[1] = 1 + u[1] u[0].real = 1.0 + u[0].real; //u = u/sqrt(u[1]) tmp = u[0].real; for(i = 0; i < n; i++) { u[i].real = u[i].real/sqrt(tmp);//I think u[0] has tpo be real here u[i].imag = u[i].imag/sqrt(tmp); } //v = -rho_bar*v rho.real = -rho.real; *v = complexMult(rho, *v); }
void copyMat(Complex *src, Complex *dest, int dim1, int dim2) { copyVect(src, dest, dim1*dim2); }
/* Algorithm taken from Matrix Algorithms Vol. II by G.W. Stewart. This function takes a vector A of order n and reduces it to Hessenberg form by Householder transformations. In the future it may be possible to remove H entirely and do the transformation in place. A is an n*n matrix that I am transforming H is an n*n matrix where I will put the result Q is an n*n matrix where I will accumulate the transformations u is a vector of length n for scratch work. vH is another vector of length n for scratch work */ void hessreduce(Complex *A, Complex *H, Complex *Q, Complex *u, Complex *vH, int n) { int k, i, j, l; Complex tmp; if(n < 2) return; //Reduce A //H = A copyMat(A,H,n,n); //3. for k = 1 to n-2 for(k = 0; k < n-2; k++) { //Generate the Transformation //housegen(H[k+1:n,k],u,H[k+1,k]) housegen(&INDEX(H,n,(k+1),k),u+k+1,&INDEX(H,n,(k+1),k),n-k-1); //5. Q[k+1:n,k] = u copyVect(u+k+1, &INDEX(Q, n, (k+1), k), n-k-1); //Premultiply the transformation //6. vH = uH*H[k+1:n,k+1:n] for(i = k+1; i < n; i++) { vH[i].real = 0.0; vH[i].imag = 0.0; for(j = k+1; j < n; j++) { tmp = INDEX(H,n,j,i); vH[i].real += u[j].real * tmp.real; vH[i].real += u[j].imag * tmp.imag;//minus minus for hermitian vH[i].imag += u[j].real * tmp.imag; vH[i].imag -= u[j].imag * tmp.real;//minus sign is for hermitian } } //7. H[k+1:n,k+1:n] = H[k+1:n, k+1:n] - u*vH for(i = k+1; i < n; i++) { for(j = k+1; j < n; j++) { INDEX(H,n,i,j).real -= u[i].real *vH[j].real; INDEX(H,n,i,j).real += u[i].imag *vH[j].imag; INDEX(H,n,i,j).imag -= u[i].real *vH[j].imag; INDEX(H,n,i,j).imag -= u[i].imag *vH[j].real; } } //H[k+2:n,k] = 0 for(i = k+2; i < n; i++) { INDEX(H,n,i,k).real = 0.0; INDEX(H,n,i,k).imag = 0.0; } //Postmultiply the transformation //9. v = H[1:n, k+1:n]*u //I will use the variable vH for v (for space). for(i = 0; i < n; i++) { vH[i].real = 0.0; vH[i].imag = 0.0; for(j = k+1; j < n; j++) { tmp = INDEX(H,n,i,j); vH[i].real += tmp.real * u[j].real; vH[i].real -= tmp.imag * u[j].imag; vH[i].imag += tmp.real * u[j].imag; vH[i].imag += tmp.imag * u[j].real; } } //10. H[1:n, k+1:n] = H[1:n,k+1:n] - v*uH for(i = 0; i < n; i++) { for(j = k+1; j < n; j++) { INDEX(H,n,i,j).real -= vH[i].real * u[j].real; INDEX(H,n,i,j).real -= vH[i].imag * u[j].imag; INDEX(H,n,i,j).imag += vH[i].real * u[j].imag; INDEX(H,n,i,j).imag -= vH[i].imag * u[j].real; } } }//end k //Accumulate the Transformations //12. Q[:,n] = e_n; Q[:,n-1] = e_(n-1) for(i = 0; i < n; i++) { INDEX(Q,n,i,(n-1)).real = 0.0; INDEX(Q,n,i,(n-1)).imag = 0.0; INDEX(Q,n,i,(n-2)).real = 0.0; INDEX(Q,n,i,(n-2)).imag = 0.0; } INDEX(Q,n,(n-1),(n-1)).real = 1.0; INDEX(Q,n,(n-2),(n-2)).real = 1.0; //13. for k = n-2 to 1 by -1 for(k = n-3; k >= 0; k--) { //14. u = Q[k+1:n,k] copyVect(&INDEX(Q,n,(k+1),k), u+k+1, n-(k+1)); //15. vH = uH*Q[k+1:n,k+1:n]//Q[k+1:n,k] = u for(i = k+1; i < n; i++) { vH[i].real = 0.0; vH[i].imag = 0.0; for(j = k+1; j < n; j++) { tmp.real = u[j].real; tmp.imag = -u[j].imag; tmp = complexMult(tmp, INDEX(Q, n, j, i)); vH[i].real += tmp.real; vH[i].imag += tmp.imag; } } //16. Q[k+1:n, k+1:n] = Q[k+1:n, k+1:n] -u*vH for(i = k+1; i < n; i++) { for(j = k+1; j < n; j++) { tmp = complexMult(u[i],vH[j]); INDEX(Q,n,i,j).real -= tmp.real; INDEX(Q,n,i,j).imag -= tmp.imag; } } //17. Q[:,k] = e_k for(i = 0; i < n; i++) { INDEX(Q,n,i,k).real = 0.0; INDEX(Q,n,i,k).imag = 0.0; } INDEX(Q,n,k,k).real = 1.0; }// 18. end for k }//end hessreduce