00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef Transform_H
00036 #define Transform_H
00037
00038 #include <cmath>
00039 #include <complex>
00040 using namespace std;
00041
00042
00043 #include "transerr.h"
00044
00045 const double PI = 3.14159265358979323846264338;
00046
00047 enum WBasis {
00048 HADOMARD,
00049 PELEY,
00050 WALSH,
00051 COOLEY
00052 };
00053
00054
00055
00056 template < class T_in, class T_out >
00057 class ITransform {
00058 public:
00059 virtual void setData( T_in *dat ) = 0;
00060 virtual void doTransform() = 0;
00061 };
00062
00063
00064
00065
00066 template< class T_in, class T_out >
00067 class WFastHT : public ITransform< T_in, T_out > {
00068 public:
00069 WFastHT( uint N_par = 8 );
00070 void setData( T_in *dat );
00071 void doTransform();
00072 T_out *getSpectrum();
00073 virtual ~WFastHT();
00074 private:
00075 void regroupe();
00076 void multiply();
00077 uint binInv( uint index );
00078 T_out *spectrum;
00079 T_out *aux;
00080 uint N, m;
00081 bool noData;
00082 };
00083
00084 template< class T_in, class T_out >
00085 WFastHT< T_in, T_out >::WFastHT( uint N_par ) : N( N_par ), noData( true )
00086 {
00087
00088 if( ((~N + 1)&N) != N ) {
00089 throw TransError::badNValue();
00090 }
00091
00092 int count = 0;
00093 for(int check = N_par; (check&1) == 0 ; count++, check >>= 1 );
00094 m = count;
00095
00096 spectrum = new T_out[N];
00097 aux = new T_out[N];
00098 }
00099
00100 template< class T_in, class T_out >
00101 WFastHT< T_in, T_out >::~WFastHT()
00102 {
00103 delete [] spectrum;
00104 delete [] aux;
00105 }
00106
00107 template< class T_in, class T_out >
00108 void WFastHT< T_in, T_out >::setData( T_in *dat )
00109 {
00110 if( dat != 0 ) {
00111 for(int i = 0; i < N; i++ ) aux[i] = static_cast< T_out >( dat[i] );
00112 noData = false;
00113 }
00114 else throw TransError::noData();
00115 }
00116
00117 template< class T_in, class T_out >
00118 void WFastHT< T_in, T_out >::doTransform()
00119 {
00120 if( noData )
00121 throw TransError::noData();
00122 else {
00123
00124 for( int stage = 0, make = N/2, turn = 1; stage < m; stage++, make /= 2, turn *= 2 ) {
00125 for( int step = 0; step < make; step++ ) {
00126
00127 T_out A = aux[2*turn*step] - aux[2*turn*step + turn];
00128 aux[2*turn*step] += aux[2*turn*step + turn];
00129 aux[2*turn*step + turn] = A;
00130 }
00131 }
00132
00133 regroupe();
00134
00135 multiply();
00136 }
00137 }
00138
00139 template< class T_in, class T_out >
00140 T_out *WFastHT< T_in, T_out>::getSpectrum()
00141 {
00142 return spectrum;
00143 }
00144
00145 template< class T_in, class T_out >
00146 void WFastHT< T_in, T_out >::regroupe()
00147 {
00148
00149
00150 for( uint i = 0, k = 0; i < N; i++ ) {
00151 if( i < N/2 ) {
00152 spectrum[i] = aux[ binInv( i ) ];
00153 }
00154 else {
00155 spectrum[i] = aux[2*k + 1];
00156 k++;
00157 }
00158 }
00159 }
00160
00161 template< class T_in, class T_out >
00162 void WFastHT< T_in, T_out >::multiply()
00163 {
00164 spectrum[0] /= N;
00165 spectrum[1] /= N;
00166
00167 double S = sqrt(2.0), coeff = 1;
00168 for(int i = 1, l_1 = 2, l_2 = l_1*2; i < m; i++, l_1 *= 2, l_2 = l_1*2 ) {
00169 coeff *= S;
00170 for(int j = l_1; j < l_2; j++) {
00171 spectrum[j] *= coeff;
00172 spectrum[j] /= N;
00173 }
00174 }
00175 }
00176
00177
00178 template< class T_in, class T_out >
00179 uint WFastHT< T_in, T_out >::binInv( uint index )
00180 {
00181 uint LMASK = 1, RMASK = N >> 1, inverse = index;
00182 bool nextIter = true;
00183
00184 while( nextIter ) {
00185 if( LMASK == RMASK ) nextIter = false;
00186 if( ( (index & LMASK) == 0 ) && ( (index & RMASK) == 0) ||
00187 ( (index & LMASK) != 0 ) && ( (index & RMASK) != 0) ) {
00188
00189 }
00190 else {
00191 if( (index & LMASK) == LMASK ) {
00192 inverse |= RMASK;
00193 inverse &= ~LMASK;
00194 }
00195 else {
00196 if( (index & RMASK) == RMASK ) {
00197 inverse |= LMASK;
00198 inverse &= ~RMASK;
00199 }
00200 }
00201 }
00202 LMASK <<= 1;
00203 RMASK >>= 1;
00204 }
00205 return inverse;
00206 }
00207
00208
00209
00210
00211 template< class T_in >
00212 class WFastFT : public ITransform< T_in, complex< double > > {
00213 public:
00214 WFastFT( uint N_par = 8 );
00215 void setData( T_in *dat );
00216 void doTransform();
00217 complex< double > *getSpectrum();
00218 virtual ~WFastFT();
00219 private:
00220 void regroupe();
00221 uint binInv( uint index );
00222 T_in *inputData;
00223 complex< double > *spectrum;
00224 uint N;
00225 bool noData;
00226 };
00227
00228 template< class T_in >
00229 WFastFT< T_in >::WFastFT( uint N_par ) : N( N_par ), noData( true )
00230 {
00231 if( ((~N + 1)&N) != N ) {
00232 throw TransError::badNValue();
00233 }
00234
00235 spectrum = new complex< double >[N];
00236 }
00237
00238 template< class T_in >
00239 WFastFT< T_in >::~WFastFT()
00240 {
00241 delete [] spectrum;
00242 }
00243
00244 template< class T_in >
00245 void WFastFT< T_in >::setData( T_in *dat )
00246 {
00247 if( dat != 0 ) {
00248 inputData = dat;
00249
00250 regroupe();
00251 noData = false;
00252 }
00253 else throw TransError::noData();
00254 }
00255
00256 template< class T_in >
00257 void WFastFT< T_in >::doTransform()
00258 {
00259 if( noData )
00260 throw TransError::noData();
00261 else {
00262 for( uint halfSize = 1; halfSize < N; halfSize *= 2) {
00263 complex< double > phaseShiftStep = polar( 1.0 , -PI/halfSize );
00264 complex< double > currentPhaseShift = polar( 1.0 );
00265 for( uint fftStep = 0; fftStep < halfSize; fftStep++ ) {
00266 for( uint i = fftStep; i < N; i += 2*halfSize ) {
00267 complex< double > A = currentPhaseShift * spectrum[i + halfSize];
00268 spectrum[i + halfSize] = spectrum[i] - A;
00269 spectrum[i] += A;
00270 }
00271 currentPhaseShift *= phaseShiftStep;
00272 }
00273 }
00274 }
00275 }
00276
00277 template< class T_in >
00278 complex< double > *WFastFT< T_in >::getSpectrum()
00279 {
00280 return spectrum;
00281 }
00282
00283 template< class T_in >
00284 void WFastFT< T_in >::regroupe()
00285 {
00286 for( uint i = 0; i < N; i++ ) {
00287 spectrum[i] = static_cast< complex< double > >( inputData[ binInv( i ) ] );
00288 }
00289 }
00290
00291 template< class T_in >
00292 uint WFastFT< T_in >::binInv( uint index )
00293 {
00294 uint LMASK = 1, RMASK = N >> 1, inverse = index;
00295 bool nextIter = true;
00296
00297 while( nextIter ) {
00298 if( LMASK == RMASK ) nextIter = false;
00299 if( ( (index & LMASK) == 0 ) && ( (index & RMASK) == 0) ||
00300 ( (index & LMASK) != 0 ) && ( (index & RMASK) != 0) ) {
00301
00302 }
00303 else {
00304 if( (index & LMASK) == LMASK ) {
00305 inverse |= RMASK;
00306 inverse &= ~LMASK;
00307 }
00308 else {
00309 if( (index & RMASK) == RMASK ) {
00310 inverse |= LMASK;
00311 inverse &= ~RMASK;
00312 }
00313 }
00314 }
00315 LMASK <<= 1;
00316 RMASK >>= 1;
00317 }
00318 return inverse;
00319 }
00320
00321
00322
00323
00324 template < class T_in, class T_out >
00325 class WFastWT : ITransform< T_in, T_out > {
00326 public:
00327 WFastWT( uint N_par = 8, WBasis bas = HADOMARD );
00328 void setData( T_in *dat );
00329 void doTransform();
00330 T_out *getSpectrum();
00331 virtual ~WFastWT();
00332 private:
00333 void regroupe();
00334 uint binInv( uint index );
00335 uint binInvGCL( uint index );
00336 uint binInvGCR( uint index );
00337 T_in *inputData;
00338 T_out *spectrum;
00339 uint N;
00340 WBasis basis;
00341 bool noData;
00342 };
00343
00344 template< class T_in, class T_out >
00345 WFastWT< T_in, T_out>::WFastWT( uint N_par, WBasis bas ) : N( N_par ), basis( bas ),
00346 noData( true )
00347 {
00348 if( ((~N + 1)&N) != N ) {
00349 throw TransError::badNValue();
00350 }
00351
00352 spectrum = new T_out[N];
00353 }
00354
00355 template< class T_in, class T_out >
00356 WFastWT< T_in, T_out >::~WFastWT()
00357 {
00358 delete [] spectrum;
00359 }
00360
00361 template< class T_in, class T_out >
00362 void WFastWT< T_in, T_out >::setData( T_in *dat )
00363 {
00364 if( dat != 0 ) {
00365 inputData = dat;
00366
00367 regroupe();
00368 noData = false;
00369 }
00370 else throw TransError::noData();
00371 }
00372
00373 template< class T_in, class T_out >
00374 void WFastWT< T_in, T_out >::doTransform()
00375 {
00376 if( noData ) {
00377 throw TransError::noData();
00378 }
00379 else {
00380 for( int halfSize = 1; halfSize < N; halfSize *= 2) {
00381 for( int fwtStep = 0; fwtStep < halfSize; fwtStep++ ) {
00382 for( int i = fwtStep; i < N; i += 2*halfSize ) {
00383 T_out A = spectrum[i + halfSize];
00384 spectrum[i + halfSize] = spectrum[i] - A;
00385 spectrum[i] += A;
00386 }
00387 }
00388 }
00389 }
00390 }
00391
00392 template< class T_in, class T_out >
00393 T_out *WFastWT< T_in, T_out >::getSpectrum()
00394 {
00395 return spectrum;
00396 }
00397
00398 template< class T_in, class T_out >
00399 void WFastWT< T_in, T_out >::regroupe()
00400 {
00401 int i;
00402 switch( basis ) {
00403 case HADOMARD:
00404 for( i = 0; i < N; i++ ) {
00405 spectrum[i] = static_cast< T_out >( inputData[i] );
00406 }
00407 break;
00408 case PELEY:
00409 for( i = 0; i < N; i++ ) {
00410 spectrum[i] = static_cast< T_out >( inputData[ binInv( i ) ] );
00411 }
00412 break;
00413 case WALSH:
00414 for( i = 0; i < N; i++ ) {
00415 int newI = binInv( i );
00416 spectrum[i] = static_cast< T_out >( inputData[ binInvGCL( newI ) ] );
00417 }
00418 break;
00419 case COOLEY:
00420 for( i = 0; i < N; i++ ) {
00421 int newI = binInv( i );
00422 spectrum[i] = static_cast< T_out >( inputData[ binInvGCR( newI ) ] );
00423 }
00424 break;
00425 default:
00426 throw TransError::noSuchBasis();
00427 }
00428 }
00429
00430 template< class T_in, class T_out >
00431 uint WFastWT< T_in, T_out >::binInv( uint index )
00432 {
00433
00434 uint LMASK = 1, RMASK = N >> 1, inverse = index;
00435 bool nextIter = true;
00436
00437 while( nextIter ) {
00438 if( LMASK == RMASK ) nextIter = false;
00439 if( ( (index & LMASK) == 0 ) && ( (index & RMASK) == 0) ||
00440 ( (index & LMASK) != 0 ) && ( (index & RMASK) != 0) ) {
00441
00442 }
00443 else {
00444 if( (index & LMASK) == LMASK ) {
00445 inverse |= RMASK;
00446 inverse &= ~LMASK;
00447 }
00448 else {
00449 if( (index & RMASK) == RMASK ) {
00450 inverse |= LMASK;
00451 inverse &= ~RMASK;
00452 }
00453 }
00454 }
00455 LMASK <<= 1;
00456 RMASK >>= 1;
00457 }
00458 return inverse;
00459 }
00460
00461
00462 template< class T_in, class T_out >
00463 uint WFastWT< T_in, T_out >::binInvGCL( uint index )
00464 {
00465 unsigned int LMASK = N >> 1, RMASK = LMASK >> 1, greyCL = 0;
00466
00467 if( ( index & LMASK ) != 0 )
00468 greyCL |= LMASK;
00469
00470 while( RMASK ) {
00471 if( ( ( greyCL & LMASK ) != 0 ) && ( ( index & RMASK ) == 0 ) ||
00472 ( ( greyCL & LMASK ) == 0 ) && ( ( index & RMASK ) != 0 ) ) {
00473 greyCL |= RMASK;
00474 }
00475 LMASK >>= 1;
00476 RMASK >>= 1;
00477 }
00478 return greyCL;
00479 }
00480
00481
00482 template< class T_in, class T_out >
00483 uint WFastWT< T_in, T_out >::binInvGCR( uint index )
00484 {
00485 unsigned int base = N >> 1;
00486 unsigned int LMASK = 1, RMASK = LMASK << 1, greyCR = 0;
00487
00488 if( ( index & LMASK ) != 0 )
00489 greyCR |= LMASK;
00490
00491 while( LMASK != base ) {
00492 if( ( ( greyCR & LMASK ) != 0 ) && ( ( index & RMASK ) == 0 ) ||
00493 ( ( greyCR & LMASK ) == 0 ) && ( ( index & RMASK ) != 0 ) ) {
00494 greyCR |= RMASK;
00495 }
00496 LMASK <<= 1;
00497 RMASK <<= 1;
00498 }
00499 return greyCR;
00500 }
00501
00502
00503
00504 template < class T_in, class T_out >
00505 class WIFastHT : public ITransform< T_in, T_out > {
00506 public:
00507 WIFastHT( uint N_par = 8 );
00508 void doTransform();
00509 void setData( T_in *dat );
00510 T_out *getSpectrum();
00511 virtual void regroupe();
00512 virtual ~WIFastHT();
00513 private:
00514 uint N, m;
00515 void multiply();
00516 T_out *spectrum;
00517 T_out *aux1;
00518 T_out *aux2;
00519 bool noData;
00520 };
00521
00522 template< class T_in, class T_out >
00523 WIFastHT< T_in, T_out>::WIFastHT( uint N_par ) : N( N_par ), noData( true )
00524 {
00525
00526 if( ((~N + 1)&N) != N ) {
00527 throw TransError::badNValue();
00528 }
00529
00530 int count = 0;
00531 for(int check = N_par; (check&1) == 0 ; count++, check >>= 1 );
00532 m = count;
00533
00534 spectrum = new T_out[ N ];
00535 aux1 = new T_out[ N ];
00536 aux2 = new T_out[ N ];
00537 }
00538
00539 template< class T_in, class T_out >
00540 WIFastHT< T_in, T_out >::~WIFastHT()
00541 {
00542 delete [] spectrum;
00543 delete [] aux1;
00544 delete [] aux2;
00545 }
00546
00547 template< class T_in, class T_out >
00548 void WIFastHT< T_in, T_out >::doTransform()
00549 {
00550 if( noData )
00551 throw TransError::noData();
00552 else {
00553 spectrum[ 0 ] = aux1[ 0 ] + aux1[ 1 ];
00554 spectrum[ 1 ] = aux1[ 0 ] - aux1[ 1 ];
00555 for( int halfSize = 2; halfSize < N; halfSize *= 2) {
00556 for( int i = 0; i < halfSize; i++ ) aux2[ i ] = spectrum[ i ];
00557 uint count = halfSize;
00558 for( int ifhtStep = 0; ifhtStep < halfSize; ifhtStep++ ) {
00559 spectrum[ 2*ifhtStep ] = aux2[ ifhtStep ] + aux1[ count ];
00560 spectrum[ 2*ifhtStep + 1 ] = aux2[ ifhtStep ] - aux1[ count ];
00561 count++;
00562 }
00563 }
00564 }
00565 }
00566
00567 template< class T_in, class T_out >
00568 void WIFastHT< T_in, T_out >::setData( T_in *dat )
00569 {
00570 for( int i = 0; i < N; i++ ) {
00571 aux1[i] = static_cast< T_out >( dat[i] );
00572 }
00573 multiply();
00574 noData = false;
00575 }
00576
00577 template< class T_in, class T_out >
00578 void WIFastHT< T_in, T_out >::multiply()
00579 {
00580 double S = sqrt(2.0), coeff = 1;
00581 for(int i = 1, l_1 = 2, l_2 = l_1*2; i < m; i++, l_1 *= 2, l_2 = l_1*2 ) {
00582 coeff *= S;
00583 for(int j = l_1; j < l_2; j++) {
00584 aux1[j] *= coeff;
00585 }
00586 }
00587 }
00588
00589 template< class T_in, class T_out >
00590 T_out *WIFastHT< T_in, T_out >::getSpectrum()
00591 {
00592 return spectrum;
00593 }
00594
00595 template< class T_in, class T_out >
00596 void WIFastHT< T_in, T_out >::regroupe()
00597 {
00598
00599 }
00600
00601 #endif
00602