00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "linalg.h"
00022 #include "helper.h"
00023 #include <string.h>
00024 #include <math.h>
00025 #include <gsl/gsl_linalg.h>
00026
00059 gsl_matrix* matrix_to_gsl( Array *in, bool alloc ){
00060 gsl_matrix *out;
00061 if( in->ndim != 2 ){
00062 errprintf("in is not a matrix, ndim=%i\n", in->ndim );
00063 }
00064 if( alloc ){
00065 out = gsl_matrix_alloc( (size_t)in->size[0], (size_t)in->size[1] );
00066 if( in->dtype==DOUBLE ){
00067 memcpy( out->data, in->data, in->nbytes );
00068 } else {
00069 int i,j;
00070 double el;
00071 for( i=0; i<in->size[0]; i++ ){
00072 for( j=0; j<in->size[1]; j++ ){
00073 array_dtype_to_double( &el, array_index2( in, i, j ), in->dtype );
00074 gsl_matrix_set( out, i, j, el );
00075 }
00076 }
00077 }
00078 } else {
00079 MALLOC( out, 1, gsl_matrix );
00080 out->size1=(size_t)in->size[0];
00081 out->size2=(size_t)in->size[1];
00082 out->tda=(size_t)in->size[1];
00083 out->data=(double*)in->data;
00084 out->owner=0;
00085 out->block=NULL;
00086 }
00087
00088 return out;
00089 }
00090
00099 Array* matrix_mean( Array *a, int dim ){
00100 Array *v;
00101 int i,j;
00102 bool ismatrix;
00103 matrix_CHECK( ismatrix, a );
00104 if( !ismatrix ) return NULL;
00105 if( dim!=0 && dim!=1 ){
00106 errprintf("wrong dimension dim=%i, must be in {0,1}\n", dim );
00107 return NULL;
00108 }
00109 double *p;
00110 v = array_new2( DOUBLE, 1, a->size[1-dim] );
00111 for( i=0; i<a->size[1-dim]; i++ ){
00112 p=&array_INDEX1( v, double, i );
00113 *p= 0.0;
00114 for( j=0; j<a->size[dim]; j++ ){
00115 array_INDEX1( v, double, i ) +=
00116 array_INDEX2( a, double, (dim==1)?i:j,(dim==1)?j:i );
00117 }
00118 array_INDEX1( v, double, i ) /= (double)a->size[dim];
00119 }
00120 return v;
00121 }
00122
00138 Array* matrix_get_row( Array *m, int row, bool alloc ){
00139 Array *rowvec;
00140 bool ismatrix;
00141 matrix_CHECK( ismatrix, m );
00142 if( !ismatrix ) return NULL;
00143 if( row<0 || row>=m->size[0] ){
00144 errprintf("Index out of bounds: %i/%i\n", row, m->size[0] );
00145 return NULL;
00146 }
00147
00148 if( !alloc ){
00149 rowvec = array_fromptr2( DOUBLE, 1, array_INDEXMEM2( m, row, 0 ),
00150 m->size[1] );
00151 } else {
00152 rowvec = array_new2( DOUBLE, 1, m->size[1] );
00153 memcpy( rowvec->data, array_INDEXMEM2( m, row, 0 ),
00154 m->size[1]*m->dtype_size );
00155 }
00156 return rowvec;
00157 }
00158
00175 Array* matrix_get_col( Array *m, int col ){
00176 Array *colvec;
00177 int i;
00178 bool ismatrix;
00179 matrix_CHECK( ismatrix, m );
00180 if( !ismatrix ) return NULL;
00181 if( col<0 || col>=m->size[1] ){
00182 errprintf("Index out of bounds: %i/%i\n", col, m->size[1] );
00183 return NULL;
00184 }
00185 colvec = array_new2( DOUBLE, 1, m->size[0] );
00186 for( i=0; i<m->size[0]; i++ ){
00187 array_INDEX1( colvec, double, i )=array_INDEX2(m, double, i, col );
00188 }
00189 return colvec;
00190 }
00191
00200 Array* matrix_mult( const Array *m1, const Array *m2 ){
00201 Array *out=NULL;
00202 int i,j,k;
00203 bool ismatrix;
00204 matrix_CHECK( ismatrix, m1 ); if( !ismatrix ) return NULL;
00205 matrix_CHECK( ismatrix, m2 ); if( !ismatrix ) return NULL;
00206 if( m1->size[1] != m2->size[0] ){
00207 errprintf("Mismatch in size, cannot calculate matrix product: %i!=%i\n",
00208 m1->size[1], m2->size[0] );
00209 return NULL;
00210 }
00211
00212 out = array_new2( DOUBLE, 2, m1->size[0], m2->size[1] );
00213
00214 double *field;
00215 for( i=0; i<out->size[0]; i++ ){
00216 for( j=0; j<out->size[1]; j++ ){
00217 field=(double*)array_INDEXMEM2( out, i, j );
00218 *field=0.0;
00219 for( k=0; k<m1->size[1]; k++ ){
00220 *field += array_INDEX2( m1, double, i, k )*
00221 array_INDEX2( m2, double, k, j );
00222 }
00223 }
00224 }
00225
00226 return out;
00227 }
00238 Array* matrix_transpose( Array *m, bool alloc ){
00239 int i,j;
00240 bool ismatrix;
00241 matrix_CHECK( ismatrix, m );
00242 if( !ismatrix ) return NULL;
00243
00244 Array *out;
00245 out = array_new2( DOUBLE, 2, m->size[1], m->size[0] );
00246 for( i=0; i<m->size[0]; i++ ){
00247 for( j=0; j<m->size[1]; j++ ){
00248 array_INDEX2( out, double, j,i) = array_INDEX2( m, double, i,j);
00249 }
00250 }
00251 if( !alloc ){
00252 memcpy( m->data, out->data, out->nbytes );
00253 array_free( out );
00254 out = m;
00255 double tmp=out->size[0];
00256 out->size[0]=out->size[1];
00257 out->size[1]=tmp;
00258 }
00259
00260 return out;
00261 }
00262
00282 Array* matrix_pca( Array *X, Array **var, bool alloc ){
00283 Array *out=NULL;
00284 int i,j;
00285 bool ismatrix;
00286 matrix_CHECK( ismatrix, X );
00287 if( !ismatrix ) return NULL;
00288
00289 int N,K;
00290 N = X->size[0];
00291 K = X->size[1];
00292
00293 Array *tmp = array_copy( X, TRUE );
00294
00295
00296 Array *mean=matrix_mean( X, 0 );
00297 for( i=0; i<N; i++ ){
00298 for( j=0; j<K; j++ ){
00299 array_INDEX2( tmp, double, i, j ) -=
00300 array_INDEX1( mean, double, j );
00301 }
00302 }
00303
00304 array_scale( tmp, 1.0/sqrt((double) N-1 ) );
00305
00306 gsl_matrix *A=matrix_to_gsl( tmp, TRUE );
00307 gsl_matrix *V=gsl_matrix_alloc( K, K );
00308 gsl_vector *S=gsl_vector_alloc( K );
00309 gsl_vector *workspace=gsl_vector_alloc( K );
00310
00311
00312 gsl_linalg_SV_decomp( A, V, S, workspace);
00313 gsl_matrix_transpose( V );
00314
00315 if( var ){
00316 (*var)=array_fromptr2( DOUBLE, 1, S->data, S->size );
00317 S->owner=0;
00318 (*var)->free_data=1;
00319 for( i=0; i<array_NUMEL( *var ); i++ ){
00320 array_INDEX1( *var, double, i ) = SQR( array_INDEX1( *var, double, i ) );
00321 }
00322 }
00323
00324 Array *Vp=array_fromptr2( DOUBLE, 2, V->data, V->size1, V->size2 );
00325 matrix_transpose( tmp, FALSE );
00326 out=matrix_mult( Vp, tmp );
00327 matrix_transpose( out, FALSE );
00328
00329 if( out->size[0]!=X->size[0] || out->size[1]!=X->size[1] ){
00330 errprintf("Input/Output dimension mismatch: (%i,%i) vs. (%i,%i)\n",
00331 X->size[0], X->size[1], out->size[0], out->size[1] );
00332 }
00333
00334 if( !alloc ){
00335 memcpy( X->data, out->data, out->nbytes );
00336 array_free( out );
00337 out = X;
00338 }
00339
00340
00341 gsl_matrix_free( A );
00342 gsl_matrix_free( V );
00343 gsl_vector_free( S );
00344 gsl_vector_free( workspace );
00345 array_free( mean );
00346 array_free( Vp );
00347 array_free( tmp );
00348
00349 return out;
00350 }