/*****************************************************************************
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 ;
}
syntax highlighted by Code2HTML, v. 0.9.1