/***************************************************************************** Major portions of this software are copyrighted by the Medical College of Wisconsin, 1994-2000, and are released under the Gnu General Public License, Version 2. See the file README.Copyright for details. ******************************************************************************/ /********************************************************************* These are the template routines to form functional images recursively from various data types. To create actual routines for this purpose, you must compile the file with the preprocessor symbol DTYPE set to one of the following types: byte short int float cc -c -DDTYPE=short afni_pcor.c mv -f afni_pcor.o afni_pcor_short.o In the example above, the resulting routine will be named PCOR_update_short and will take as input a "short *" (plus the other stuff, which isn't DTYPE dependent). **********************************************************************/ #ifndef DTYPE #error "Cannot compile, since DTYPE is undefined." #endif #undef MAIN #include "afni_pcor.h" /** macros for function names defined in this file **/ #define PCOR_UPDATE TWO_TWO(PCOR_update_,DTYPE) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*** update all voxels with a new array of data inputs: vdata = array[nvox] of new data for each voxel ref = pointer to references structure to use vc = pointer to correlation data structure output: updated vc ***/ void PCOR_UPDATE( DTYPE * vdata , PCOR_references * ref , PCOR_voxel_corr * vc ) { int vox , jj , /* loop indices */ nv = vc->nvox , /* number of voxels */ nr = vc->nref ; /* number of references */ float *aaa = ref->alp , *fff = ref->ff , *ggg = ref->gg ; float zz , bq = ref->betasq ; /*** check inputs for OK-ness ***/ if( vc->nref != ref->nref ){ fprintf( stderr , "PCOR_UPDATE: reference size mismatch!\n" ) ; EXIT(1) ; } /**---------------------------------------------------------------------- innermost loop expansion is for speedup if nref is small, if enabled UPZZ updates zz for each row element > This pair is performed for UPCH updates the Cholesky row element > each non-diagonal element UPLL updates the Cholesky diagonal element -------------------------------------------------------------------------**/ #ifdef EXPAND_UPDATE # define UPZZ(j) zz -= aaa[j] * VCH(vc,vox,j) # define UPCH(j) VCH(vc,vox,j) = fff[j] * VCH(vc,vox,j) + ggg[j] * zz # define UPLL(j) VCH(vc,vox,j) += bq * zz * zz switch( nr ){ default: /*** generic case: nested loops ***/ #endif /*** for each voxel ***/ for( vox=0 ; vox < nv ; vox++ ){ /*** update last row of each Cholesky factor ***/ zz = (float) vdata[vox] ; for( jj=0 ; jj < nr ; jj++ ){ zz -= aaa[jj] * VCH(vc,vox,jj) ; VCH(vc,vox,jj) = fff[jj] * VCH(vc,vox,jj) + ggg[jj] * zz ; } VCH(vc,vox,nr) += bq * zz * zz ; /* square of true Cholesky diagonal */ } #ifdef EXPAND_UPDATE break ; /***------------------------------------------------------------ Below here are the special cases for 1-9 reference waveforms: The above loop over jj is just unrolled manually (using the UP?? macros) in order to gain speed. ----------------------------------------------------------------***/ case 1: for( vox=0 ; vox < nv ; vox++ ){ zz = (float) vdata[vox] ; UPZZ(0) ; UPCH(0) ; UPLL(1) ; } break ; case 2: for( vox=0 ; vox < nv ; vox++ ){ zz = (float) vdata[vox] ; UPZZ(0) ; UPCH(0) ; UPZZ(1) ; UPCH(1) ; UPLL(2) ; } break ; case 3: for( vox=0 ; vox < nv ; vox++ ){ zz = (float) vdata[vox] ; UPZZ(0) ; UPCH(0) ; UPZZ(1) ; UPCH(1) ; UPZZ(2) ; UPCH(2) ; UPLL(3) ; } break ; case 4: for( vox=0 ; vox < nv ; vox++ ){ zz = (float) vdata[vox] ; UPZZ(0) ; UPCH(0) ; UPZZ(1) ; UPCH(1) ; UPZZ(2) ; UPCH(2) ; UPZZ(3) ; UPCH(3) ; UPLL(4) ; } break ; case 5: for( vox=0 ; vox < nv ; vox++ ){ zz = (float) vdata[vox] ; UPZZ(0) ; UPCH(0) ; UPZZ(1) ; UPCH(1) ; UPZZ(2) ; UPCH(2) ; UPZZ(3) ; UPCH(3) ; UPZZ(4) ; UPCH(4) ; UPLL(5) ; } break ; case 6: for( vox=0 ; vox < nv ; vox++ ){ zz = (float) vdata[vox] ; UPZZ(0) ; UPCH(0) ; UPZZ(1) ; UPCH(1) ; UPZZ(2) ; UPCH(2) ; UPZZ(3) ; UPCH(3) ; UPZZ(4) ; UPCH(4) ; UPZZ(5) ; UPCH(5) ; UPLL(6) ; } break ; case 7: for( vox=0 ; vox < nv ; vox++ ){ zz = (float) vdata[vox] ; UPZZ(0) ; UPCH(0) ; UPZZ(1) ; UPCH(1) ; UPZZ(2) ; UPCH(2) ; UPZZ(3) ; UPCH(3) ; UPZZ(4) ; UPCH(4) ; UPZZ(5) ; UPCH(5) ; UPZZ(6) ; UPCH(6) ; UPLL(7) ; } break ; case 8: for( vox=0 ; vox < nv ; vox++ ){ zz = (float) vdata[vox] ; UPZZ(0) ; UPCH(0) ; UPZZ(1) ; UPCH(1) ; UPZZ(2) ; UPCH(2) ; UPZZ(3) ; UPCH(3) ; UPZZ(4) ; UPCH(4) ; UPZZ(5) ; UPCH(5) ; UPZZ(6) ; UPCH(6) ; UPZZ(7) ; UPCH(7) ; UPLL(8) ; } break ; case 9: for( vox=0 ; vox < nv ; vox++ ){ zz = (float) vdata[vox] ; UPZZ(0) ; UPCH(0) ; UPZZ(1) ; UPCH(1) ; UPZZ(2) ; UPCH(2) ; UPZZ(3) ; UPCH(3) ; UPZZ(4) ; UPCH(4) ; UPZZ(5) ; UPCH(5) ; UPZZ(6) ; UPCH(6) ; UPZZ(7) ; UPCH(7) ; UPZZ(8) ; UPCH(8) ; UPLL(9) ; } break ; } #endif /* EXPAND_UPDATE */ (vc->nupdate)++ ; /* June 1995: another update completed! */ return ; }