/* Author: G. Jungman * RCS: $Id: svd.c,v 1.1 1999/10/19 11:15:28 bjg Exp $ */ /* Simple linear algebra operations, operating directly * on the gsl_vector and gsl_matrix objects. These are * meant for "generic" and "small" systems. Anyone * interested in large systems will want to use more * sophisticated methods, presumably involving native * BLAS operations, specialized data representations, * or other optimizations. */ #include #include #include #include #include #include #include "gsl_linalg.h" #define REAL double int gsl_la_decomp_SV_impl(gsl_matrix * A, gsl_matrix * Q, gsl_vector * S, double tolerance) { if(A == 0 || Q == 0 || S == 0) { return GSL_EFAULT; } else if(Q->size1 != A->size2 || Q->size1 != Q->size2 || S->size != A->size2) { return GSL_EBADLEN; } else { const int nrow = A->size1; const int ncol = A->size2; int i,j,k; /* Initialize the rotation counter and the sweep counter. */ int count = 1; int sweep = 0; int sweepmax = ncol; /* Always do at least 12 sweeps. */ sweepmax = GSL_MAX(sweepmax, 12); /* Set Q to the identity matrix. */ for(i=0; i 0 && sweep <= sweepmax){ /* Initialize rotation counter. */ count = ncol*(ncol-1)/2; for(j=0; j GSL_DBL_MIN)) { /* underflow occured or will occur */ return GSL_EUNDRFLW; } if(q*r == 0.0) { /* column elements of A are vanishingly small */ count--; continue; } if((double)(p*p)/(double)(q*r) < tolerance) { /* columns j,k orthogonal * note that p*p/(q*r) is automatically <= 1.0 */ count--; continue; } /* calculate rotation angles */ if(q < r) { cosine = 0.0; sine = 1.0; } else { q -= r; v = sqrt(4.0*p*p + q*q); cosine = sqrt((v+q)/(2.0*v)); sine = p/(v*cosine); } /* apply rotation to A */ for(i=0; i 0) { /* reached sweep limit */ } for(j=0; j