123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- /*Daala video codec
- Copyright (c) 2005-2008 Daala project contributors. All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- - 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.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <float.h>
- #include <math.h>
- #include <string.h>
- #include "svd.h"
- #include "pythag.h"
- /*Computes the singular value decomposition of a matrix into matrices
- U\Sigma V^T, where U and V are orthonormal and \Sigma is diagonal.
- _w: An _nrows by (_nrows+_ncols) matrix of storage for input and output.
- On input, the first _nrows rows contain the input matrix.
- On output, the first _nrows rows contain the columns of U, each
- scaled by the corresponding singular value.
- The caller must divide by the appropriate value to obtain a unit
- vector, if one is desired.
- The next _ncols rows contain the rows of V (_not_ V^T).
- _s: On output contains the squares of the _ncols singular values.
- _nrows: The number of rows of the matrix.
- _ncols: The number of columns of the matrix.
- Return: The estimated column rank of the matrix.*/
- int svd(double **_w,double *_s,int _nrows,int _ncols){
- double e2;
- double tol;
- int i;
- int j;
- int col_rank;
- int slimit;
- int sweepi;
- int nrots;
- e2=8*_nrows*DBL_EPSILON*DBL_EPSILON;
- tol=0.125*DBL_EPSILON;
- for(i=0;i<_ncols;i++)for(j=0;j<_ncols;j++)_w[i+_nrows][j]=i==j;
- col_rank=_ncols;
- slimit=_ncols>24?_ncols>>2:6;
- sweepi=0;
- do{
- int k;
- nrots=0;
- for(j=0;j<col_rank-1;j++)for(k=j+1;k<col_rank;k++){
- double vt;
- double ee;
- double ff;
- double gg;
- double c;
- double s;
- double x;
- double y;
- ff=ee=gg=0;
- for(i=0;i<_nrows;i++){
- ee+=_w[i][j]*_w[i][j];
- ff+=_w[i][j]*_w[i][k];
- gg+=_w[i][k]*_w[i][k];
- }
- _s[j]=ee;
- _s[k]=gg;
- if(ee>=gg){
- if(ee<=e2*_s[0]||fabs(ff)<=tol*ee)continue;
- ff/=ee;
- gg=1-gg/ee;
- vt=pythag(2*ff,gg);
- c=sqrt(fabs(0.5*(1+gg/vt)));
- s=ff/(vt*c);
- }
- else{
- ff/=gg;
- ee=ee/gg-1;
- vt=pythag(2*ff,ee);
- s=sqrt(fabs(0.5*(1-ee/vt)));
- if(ff<0)s=-s;
- c=ff/(vt*s);
- }
- for(i=0;i<_nrows+_ncols;i++){
- x=_w[i][j];
- y=_w[i][k];
- _w[i][j]=x*c+y*s;
- _w[i][k]=y*c-x*s;
- }
- nrots++;
- }
- while(col_rank>1&&_s[col_rank-1]<=_s[0]*tol+tol*tol)col_rank--;
- }
- while(nrots>0&&++sweepi<=slimit);
- return col_rank-(col_rank>0&&_s[0]<=0);
- }
- /*Computes the Moore-Penrose pseudoinverse of a matrix using an SVD.
- _w: An _nrows by (_nrows+_ncols) matrix of storage for input and output.
- On input, the first _nrows rows contain the input matrix.
- On output, the first _nrows rows contain the transpose of the
- pseudoinverse.
- The next _ncols rows are temporary storage.
- On output the contents are undefined.
- _s: _ncols temporary values.
- On output the contents are undefined.
- _nrows: The number of rows of the matrix.
- _ncols: The number of columns of the matrix.
- Return: The estimated column rank of the matrix.*/
- int svd_pseudoinverse(double **_w,double *_s,int _nrows,int _ncols){
- int rank;
- int i;
- int j;
- int k;
- rank=svd(_w,_s,_nrows,_ncols);
- /*There are generally far fewer columns than rows.
- Fold the singular value inverses into V.*/
- for(j=0;j<_ncols;j++)for(i=0;i<rank;i++)_w[_nrows+j][i]/=_s[i];
- /*Recompose the remaining matrices.*/
- for(i=0;i<_nrows;i++){
- memset(_s,0,_ncols*sizeof(*_s));
- for(j=0;j<_ncols;j++)for(k=0;k<rank;k++)_s[j]+=_w[i][k]*_w[_nrows+j][k];
- memcpy(_w[i],_s,_ncols*sizeof(*_s));
- }
- return rank;
- }
|