⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svdcmp.c

📁 统计模式识别算法包
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************//*                                                                            *//*  SVDCMP  -  SingularValueDecomp object routines for performing singular    *//*             value decomposition on a matrix, and using backsubstitution    *//*             to find least squares solutions to simultaneous equations.     *//*                                                                            *//*             The decomposition algorithm is yet another implementation of   *//*             the classic method of Golub and Reinsch (Wilkinson, J.H. and   *//*             Reinsch, C., 1971, 'Handbook for Automatic Computation' vol. 2)*//*             Some tricks have been taken from later sources.  See (Press    *//*             et al 'Numerical Recipes in C') for a complete list of         *//*             references.                                                    *//*                                                                            *//* Copyright (c) 1993 by Academic Press, Inc.                                 *//*                                                                            *//* All rights reserved.  Permission is hereby granted, until further notice,  *//* to make copies of this diskette, which are not for resale, provided these  *//* copies are made from this master diskette only, and provided that the      *//* following copyright notice appears on the diskette label:                  *//* (c) 1993 by Academic Press, Inc.                                           *//*                                                                            *//* Except as previously stated, no part of the computer program embodied in   *//* this diskette may be reproduced or transmitted in any form or by any means,*//* electronic or mechanical, including input into storage in any information  *//* system for resale, without permission in writing from the publisher.       *//*                                                                            *//* Produced in the United States of America.                                  *//*                                                                            *//* ISBN 0-12-479041-0                                                         *//*                                                                            *//******************************************************************************/#include <stdio.h>#include <string.h>#include <math.h>#include <ctype.h>#include <stdlib.h>#include "const.h"       // System and limitation constants, typedefs, structs#include "classes.h"     // Includes all class headers#include "funcdefs.h"    // Function prototypes/*   Prototypes for local subroutines*/static double bidiag ( double *a , int rows , int cols , double *w ,                       double *work ) ;static void cancel ( int rows , int cols , int lower , int index ,                     double matnorm , double *a , double *w , double *work ) ;static void qr ( int rows , int cols , int lower , int index ,                 double *a , double *v , double *w , double *work ) ;static void transforms ( double *a , int rows , int cols , double *w ,                         double *v , double *work ) ;static void verify_nonneg ( int cols , int index , double *w , double *v ) ;/*   Local macros.  RSS computes the root of the sum of squares of   its arguments.  This clever implementation avoids over/underflow.   SIGN is the old FORTRAN routine which returns the value of its   first argument with the sign of its second.   The variables va, vb and vc are local work areas for these macros.*/static double va, vb, vc ;#define RSS(a,b) ((va=fabs(a)) > (vb=fabs(b)) ? \                 (vc=vb/va , va*sqrt(vc*vc+1.0)) : \                 ((vb != 0.0) ? (vc=va/vb , vb*sqrt(vc*vc+1.0)) : 0.0))#define SIGN(a,b) (va=fabs(a) , (b) >= 0.0 ? va : -va)/*--------------------------------------------------------------------------------   Constructor - This allocates memory for the input/output matrix 'a' and                 any work areas which it will need (including the public                 outputs of w and v).  It also allocates 'b' which will be                 input to the backsub routine.  It does not allocate 'x' which                 is the output of backsub.                 If there is a problem (rows < cols, or insufficient memory),                 it leaves public ok=0.  The user should check for this after                 allocating with new.--------------------------------------------------------------------------------*/SingularValueDecomp::SingularValueDecomp ( int nrows , int ncols , int preserve){   if (nrows < ncols) {      rows = cols = ok = 0 ;      return ;      }   a = u = w = v = work = b = NULL ;   if (((a = (double *) MALLOC ( nrows * ncols * sizeof(double) )) == NULL)    || (preserve  &&        (u = (double *) MALLOC ( nrows * ncols * sizeof(double)))== NULL)    || ((w = (double *) MALLOC ( ncols * sizeof(double) )) == NULL)    || ((v = (double *) MALLOC ( ncols * ncols * sizeof(double) )) == NULL)    || ((work = (double *) MALLOC ( ncols * sizeof(double) )) == NULL)    || ((b = (double *) MALLOC ( nrows * sizeof(double) )) == NULL)) {      if (a != NULL)         FREE ( a ) ;      if (u != NULL)         FREE ( u ) ;      if (w != NULL)         FREE ( w ) ;      if (v != NULL)         FREE ( v ) ;      if (work != NULL)         FREE ( work ) ;      if (b != NULL)         FREE ( b ) ;      rows = cols = ok = 0 ;      return ;      }   rows = nrows ;   cols = ncols ;   ok = 1 ;}/*--------------------------------------------------------------------------------   Destructor - This frees all memory allocated by the constructor.--------------------------------------------------------------------------------*/SingularValueDecomp::~SingularValueDecomp (){   if (! ok)    // If constructor's mallocs failed      return ;  // there is nothing to free   FREE ( a ) ;   if (u != NULL)    // This was allocated only if preserve was nonzero      FREE ( u ) ;   FREE ( w ) ;   FREE ( v ) ;   FREE ( work ) ;   FREE ( b ) ;}/*--------------------------------------------------------------------------------   svdcmp - Perform singular value decomposition on the matrix already stored.--------------------------------------------------------------------------------*/void SingularValueDecomp::svdcmp (){   int cflag, iter, index, lower ;   double matnorm, *mat ;   if (u == NULL)    // Do we replace a with u      mat = a ;   else {            // or preserve it?      memcpy ( u , a , rows * cols * sizeof(double) ) ;      mat = u ;      }   matnorm = bidiag ( mat , rows , cols , w , work ) ; // Reduce to bidiagonal   transforms ( mat , rows , cols , w , v , work ) ;   // Accumulate R&L trans   for (index=cols-1 ; index>=0 ; index--) { // All singular values      for (iter=0 ; iter<100 ; iter++) {     // Conservative limit on QR tries         cflag = 1 ;         for (lower=index ; lower ; lower--) { // Split?            if (fabs (work[lower]) + matnorm == matnorm) {               cflag = 0 ;               break ;               }            if (fabs (w[lower-1]) + matnorm == matnorm)               break ;            }         if (lower && cflag)            cancel ( rows , cols , lower , index , matnorm , mat , w , work ) ;         if (lower == index) {  // Converged?            verify_nonneg ( cols , index , w , v ) ; // Want nonegative singvals            break ;            }         qr ( rows , cols , lower , index , mat , v , w , work ) ; // Another QR         }      }}/*--------------------------------------------------------------------------------   bidiag - Local routine for Householder reduction to bidiagonal form--------------------------------------------------------------------------------*/static double bidiag (   double *a ,   int rows ,   int cols ,   double *w ,   double *work   ){   int col, j, k, nextcol ;   double pp, qq, denom, sum ;   double matnorm, scale ;   matnorm = qq = sum = scale = 0.0 ;   for (col=0 ; col<cols ; col++) {      nextcol = col + 1 ;      work[col] = scale * qq ;      qq = sum = scale = 0.0 ;      for (k=col ; k<rows ; k++)         scale += fabs ( a[k*cols+col] ) ;      if (scale > 0.0) {         for (k=col ; k<rows ; k++) {            a[k*cols+col] /= scale ;            sum += a[k*cols+col] * a[k*cols+col] ;            }         pp = a[col*cols+col] ;         qq = -SIGN ( sqrt(sum) , pp ) ;         denom = pp * qq - sum ;         a[col*cols+col] = pp - qq ;         for (j=nextcol ; j<cols ; j++) {            sum = 0.0 ;            for (k=col ; k<rows ; k++)               sum += a[k*cols+col] * a[k*cols+j] ;            pp = sum / denom ;            for (k=col ; k<rows ; k++)               a[k*cols+j] += pp * a[k*cols+col] ;            }         for (k=col ; k<rows ; k++)            a[k*cols+col] *= scale ;         } // if scale > 0      w[col] = scale * qq ;      qq = sum = scale = 0.0 ;      for (k=nextcol ; k<cols ; k++)         scale += fabs ( a[col*cols+k] ) ;      if (scale > 0.0) {         for (k=nextcol ; k<cols ; k++) {            a[col*cols+k] /= scale ;            sum += a[col*cols+k] * a[col*cols+k] ;            }         pp = a[col*cols+nextcol] ;         qq = -SIGN ( sqrt ( sum ) , pp ) ;         denom = pp * qq - sum ;         a[col*cols+nextcol] = pp - qq ;         for (k=nextcol ; k<cols ; k++)            work[k] = a[col*cols+k] / denom ;         if (col != rows-1) {            for (j=nextcol ; j<rows ; j++) {               sum = 0.0 ;               for (k=nextcol ; k<cols ; k++)                  sum += a[j*cols+k] * a[col*cols+k] ;               for (k=nextcol ; k<cols ; k++)                  a[j*cols+k] += sum * work[k] ;               }            }         for (k=nextcol ; k<cols ; k++)            a[col*cols+k] *= scale ;         }      sum = fabs (w[col]) + fabs (work[col]) ;      if (sum > matnorm)         matnorm = sum ;      }   return matnorm ;}/*--------------------------------------------------------------------------------   cancel--------------------------------------------------------------------------------*/static void cancel (   int rows ,   int cols ,   int lower ,   int index ,   double matnorm ,   double *a ,   double *w ,   double *work   ){   int col, row ;   double c, rr, ww, hypot, s, pp, qq ;   s = 1.0 ;   for (col=lower ; col<=index ; col++) {      rr = s * work[col] ;      if (fabs (rr) + matnorm != matnorm) {         ww = w[col] ;         hypot = RSS ( rr , ww ) ;         w[col] = hypot ;         c =  ww / hypot ;         s = -rr / hypot ;         for (row=0 ; row<rows ; row++) {            pp = a[row*cols+lower-1] ;            qq = a[row*cols+col] ;            a[row*cols+lower-1] = qq * s  +  pp * c ;            a[row*cols+col] = qq * c  -  pp * s ;            }         }      }}/*--------------------------------------------------------------------------------   Cumulate right and left transforms--------------------------------------------------------------------------------*/static void transforms (   double *a ,   int rows ,   int cols ,   double *w ,   double *v ,   double *work   ){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -