/* *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* */ /* ** Copyright UCAR (c) 1990 - 2016 */ /* ** University Corporation for Atmospheric Research (UCAR) */ /* ** National Center for Atmospheric Research (NCAR) */ /* ** Boulder, Colorado, USA */ /* ** BSD licence applies - redistribution and use in source and binary */ /* ** forms, with or without modification, are permitted provided that */ /* ** the following conditions are met: */ /* ** 1) If the software is modified to produce derivative works, */ /* ** such modified software should be clearly marked, so as not */ /* ** to confuse it with the version available from UCAR. */ /* ** 2) Redistributions of source code must retain the above copyright */ /* ** notice, this list of conditions and the following disclaimer. */ /* ** 3) Redistributions in binary form must reproduce the above copyright */ /* ** notice, this list of conditions and the following disclaimer in the */ /* ** documentation and/or other materials provided with the distribution. */ /* ** 4) Neither the name of UCAR nor the names of its contributors, */ /* ** if any, may be used to endorse or promote products derived from */ /* ** this software without specific prior written permission. */ /* ** DISCLAIMER: THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS */ /* ** OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* */ /************************************************************************ Module: usvd.c Author: C S Morse Date: Thu Sep 25 17:56:14 2003 Description: Routines for Singular Value Decomposition ************************************************************************/ /* System include files / Local include files */ #include #include #include #include #include /* Constant definitions / Macro definitions / Type definitions */ #define MAX_ITERATIONS 30 /* External global variables / Non-static global variables / Static globals */ static double DefaultMaxConditionNumber = 1e5; /* External functions / Internal global functions / Internal static functions */ /************************************************************************ Function Name: upolynomial Description: polynomial basis functions Returns: none Globals: none Notes: ************************************************************************/ void upolynomial( double x, /* I - specific x to evaluate */ int n, /* I - order of polynomial (size of xfunc) */ double *xfunc /* O - polynomial functions of x */ ) { int i; xfunc[0] = 1.0; for ( i=1; i= 0 ; -1 otherwise Globals: none Notes: ************************************************************************/ static double sign( double x ) { return (x >= 0.0) ? 1.0 : -1.0; } /************************************************************************ Function Name: usvd Description: determines singular value decomposition A = U S Vtranspose of a real (nrow x ncol) rectangular matrix, A. Returns: 0 on success; negative error code otherwise (see notes) Globals: none Notes: This subroutine is a translation from the FORTRAN version dated august 1983 by burton s. garbow, mathematics and computer science div, argonne national laboratory which in turn was a translation of the algol procedure svd, num. math. 14, 403-420(1970) by golub and reinsch. handbook for auto. comp., vol ii-linear algebra, 134-151(1971). Below are comments from the garbow FORTRAN version, modified as per the modifications for this version in c. this subroutine determines the singular value decomposition a=usv(transpose) of a real nrow by ncol rectangular matrix. householder bidiagonalization and a variant of the qr algorithm are used. on input nrow is the number of rows of a (and u). ncol is the number of columns of a (and u) and the order of v. a contains the rectangular input matrix to be decomposed. on output a is unaltered (unless overwritten by u or v). w contains the n (non-negative) singular values of a (the diagonal elements of s). they are unordered. if an error exit is made, the singular values should be correct for indices ierr+1,ierr+2,...,n. u contains the matrix u (orthogonal column vectors) of the decomposition. u may coincide with a. if an error exit is made, the columns of u corresponding to indices of correct singular values should be correct. v contains the matrix v (orthogonal) of the decomposition if an error exit is made, the columns of v corresponding to indices of correct singular values should be correct. ierr is set to zero for normal return, k if the k-th singular value has not been determined after 30 iterations. rv1 is a temporary storage array. calls pythag for dsqrt(a*a + b*b) . ************************************************************************/ int usvd( double **a, /* I - matrix to decompose */ int nrow, /* I - number of rows in a */ int ncol, /* I - number of columns in a */ double **u, /* O - matrix nrow x ncol */ double **v, /* O - matrix ncol x ncol */ double *w /* O - array (ncol) diagonal elements */ ) { double *rv1; double c, f,g,h, s, x,y,z; double scale, tst1, tst2; int converged, its; int i,j,k,l, i1,k1,l1, mn; /* copy the input A matrix into U */ for ( i=0; i=0; --i ) { if ( i < ncol-1 ) { if ( g != 0.0 ) { /* double division avoids possible overflow */ for ( j=l; j=0; --i ) { l = i + 1; g = w[i]; if ( i != ncol ) for ( j=l; j=0; --k ) { k1 = k - 1; converged = 0; its = 0; while( !converged ) { for ( l=k; l>=0; --l ) { l1 = l - 1; tst2 = tst1 + fabs(rv1[l]); if ( tst2 == tst1 ) break; tst2 = tst1 + fabs(w[l1]); if ( tst2 == tst1 ) { /* cancellation of rv1[l] if l > 0 */ c = 0.0; s = 1.0; for ( i=l; i<=k; ++i ) { f = s * rv1[i]; rv1[i] *= c; tst2 = tst1 + fabs(f); if ( tst2 == tst1 ) break; g = w[i]; h = pythag(f,g); w[i] = h; c = g / h; s = -f / h; for ( j=0; j