123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <math.h>
- #include <stdlib.h>
- #include "od_defs.h"
- #include "od_covmat.h"
- #define PRINT_COLLAPSE (0)
- void od_covmat_init(od_covmat *_this,int _sz){
- _this->sz=_sz;
- _this->mean=(double *)malloc(sizeof(*_this->mean)*_this->sz);
- _this->cov=(double *)malloc(sizeof(*_this->cov)*_this->sz*_this->sz);
- _this->work=(double *)malloc(sizeof(*_this->work)*_this->sz);
- od_covmat_reset(_this);
- }
- void od_covmat_clear(od_covmat *_this){
- free(_this->mean);
- free(_this->cov);
- free(_this->work);
- }
- void od_covmat_reset(od_covmat *_this){
- int j;
- int i;
- _this->w=0;
- for(j=0;j<_this->sz;j++){
- _this->mean[j]=0;
- for(i=0;i<_this->sz;i++){
- _this->cov[_this->sz*j+i]=0;
- }
- }
- }
- void cov_update(double *_mean,double *_cov,double *_work,double *_weight,int _n,
- const double *_data,double _w){
- double s;
- int j;
- int i;
- if(_w==0){
- return;
- }
- (*_weight)+=_w;
- s=_w/(*_weight);
- for(i=0;i<_n;i++){
- _work[i]=_data[i]-_mean[i];
- #if FAST_MATH
- _mean[i]+=_work[i]*s;
- #else
- _mean[i]+=_work[i]*_w/(*_weight);
- #endif
- }
- s*=(*_weight)-_w;
- for(j=0;j<_n;j++){
- for(i=0;i<_n;i++){
- #if FAST_MATH
- _cov[_n*j+i]+=_work[j]*_work[i]*s;
- #else
- _cov[_n*j+i]+=_work[j]*_work[i]*((*_weight)-_w)/(*_weight);
- #endif
- }
- }
- }
- void od_covmat_add(od_covmat *_this,const double *_data,double _w){
- #if 0
- cov_update(_this->mean,_this->cov,_this->work,&_this->w,_this->sz,_data,_w);
- #else
- double s;
- int i;
- int j;
- if(_w==0){
- return;
- }
- _this->w+=_w;
- s=_w/_this->w;
- for(i=0;i<_this->sz;i++){
- _this->work[i]=_data[i]-_this->mean[i];
- #if FAST_MATH
- _this->mean[i]+=_this->work[i]*s;
- #else
- _this->mean[i]+=_this->work[i]*_w/_this->w;
- #endif
- }
- s*=_this->w-_w;
- for(j=0;j<_this->sz;j++){
- for(i=0;i<_this->sz;i++){
- #if FAST_MATH
- _this->cov[_this->sz*j+i]+=_this->work[j]*_this->work[i]*s;
- #else
- _this->cov[_this->sz*j+i]+=
- _this->work[j]*_this->work[i]*(_this->w-_w)/_this->w;
- #endif
- }
- }
- #endif
- }
- void od_covmat_combine(od_covmat *_a,const od_covmat *_b){
- od_covmat_update(_a,_b->cov,_b->mean,_b->w);
- }
- void od_covmat_update(od_covmat *_this,const double *_cov,const double *_mean,
- double _w){
- double s;
- int i;
- int j;
- if(_w==0){
- return;
- }
- s=_w/(_this->w+_w);
- for(i=0;i<_this->sz;i++){
- _this->work[i]=_mean[i]-_this->mean[i];
- #if FAST_MATH
- _this->mean[i]+=_this->work[i]*s;
- #else
- _this->mean[i]+=_this->work[i]*_w/(_this->w+_w);
- #endif
- }
- s*=_this->w;
- for(i=0;i<_this->sz;i++){
- for(j=0;j<_this->sz;j++){
- #if FAST_MATH
- _this->cov[_this->sz*i+j]+=_cov[_this->sz*i+j]+
- _this->work[i]*_this->work[j]*s;
- #else
- _this->cov[_this->sz*i+j]+=_cov[_this->sz*i+j]+
- _this->work[i]*_this->work[j]*_this->w*_w/(_this->w+_w);
- #endif
- }
- }
- _this->w+=_w;
- }
- void od_covmat_correct(od_covmat *_this){
- double s;
- int j;
- int i;
- s=1/_this->w;
- for(j=0;j<_this->sz;j++){
- for(i=0;i<_this->sz;i++){
- #if FAST_MATH
- _this->cov[_this->sz*j+i]*=s;
- #else
- _this->cov[_this->sz*j+i]/=_this->w;
- #endif
- }
- }
- }
- void od_covmat_normalize(od_covmat *_this){
- int i;
- int j;
- for(i=0;i<_this->sz;i++){
- _this->work[i]=sqrt(_this->cov[_this->sz*i+i]);
- }
- for(j=0;j<_this->sz;j++){
- for(i=0;i<_this->sz;i++){
- _this->cov[_this->sz*j+i]/=_this->work[j]*_this->work[i];
- }
- }
- }
- static void covariance_collapse(const double *_cov,int _sz,int _n,double *_r,
- double *_work){
- int m;
- int i;
- int j;
- int u;
- int v;
- m=_sz/_n;
- for(i=0;i<_sz;i++){
- _r[i]=0;
- _work[i]=0;
- }
- for(v=0;v<_n;v++){
- for(u=v;u<_n;u++){
- for(j=0;j<m;j++){
- for(i=j;i<m;i++){
- _r[(u-v)*m+(i-j)]+=_cov[(v*m+j)*_sz+(u*m+i)];
- _r[(u-v)*m+(i-j)]+=_cov[(v*m+i)*_sz+(u*m+j)];
- _r[(u-v)*m+(i-j)]+=_cov[(u*m+j)*_sz+(v*m+i)];
- _r[(u-v)*m+(i-j)]+=_cov[(u*m+i)*_sz+(v*m+j)];
- _work[(u-v)*m+(i-j)]+=4;
- }
- }
- }
- }
- for(i=0;i<_sz;i++){
- _r[i]/=_work[i];
- }
- }
- void od_covmat_collapse(od_covmat *_this,int _n,double *_r){
- covariance_collapse(_this->cov,_this->sz,_n,_r,_this->work);
- #if PRINT_COLLAPSE
- for(i=0;i<_this->sz;i++){
- fprintf(stderr,"%s %- 24.18G",i>0?",":"",_r[i]);
- }
- fprintf(stderr,"\n");
- #endif
- }
- static void covariance_expand(double *_cov,int _sz,int _n,const double *_r){
- int i;
- int j;
- int u;
- int v;
- int m;
- m=_sz/_n;
- for(v=0;v<_n;v++){
- for(u=0;u<_n;u++){
- for(j=0;j<m;j++){
- for(i=0;i<m;i++){
- _cov[(v*m+j)*_sz+u*m+i]=_r[abs(v-u)*m+abs(i-j)];
- }
- }
- }
- }
- }
- void od_covmat_expand(od_covmat *_this,int _n,const double *_r){
- covariance_expand(_this->cov,_this->sz,_n,_r);
- }
- void od_covmat_print(od_covmat *_this,FILE *_fp){
- int i;
- int j;
- for(i=0;i<_this->sz;i++){
- fprintf(_fp,"%s %- 24.18G",i>0?",":"",_this->mean[i]);
- }
- fprintf(_fp,"\n");
- for(j=0;j<_this->sz;j++){
- for(i=0;i<_this->sz;i++){
- fprintf(_fp,"%s %- 24.18G",i>0?",":"",_this->cov[_this->sz*j+i]);
- }
- fprintf(_fp,"\n");
- }
- }
|