Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

Hankel.cc

Go to the documentation of this file.
00001 /*
00002 
00003     Hankel transform (Abel transform followed by FFT)
00004     Copyright (C) 1995 Colorado School of Mines. All rights reserved.
00005     Copyright (C) 2001-2003 Jussi Laako
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 
00021     Source converted from cwplib (by Dave Hale and Lydia Deng / Colorado 
00022     School of Mines).
00023 
00024     References:
00025     Hansen, E. W., 1985, Fast Hankel transform algorithm:  IEEE Trans. on
00026     Acoustics, Speech and Signal Processing, v. ASSP-33, n. 3, p. 666-671.
00027     (Beware of several errors in the equations in this paper!)
00028 
00029 */
00030 
00031 
00032 #ifdef USE_INTEL_MATH
00033     #include <mathimf.h>
00034 #else
00035     #include <math.h>
00036 #endif
00037 #include <float.h>
00038 
00039 #include "dsp/Hankel.hh"
00040 
00041 
00042 #define ABEL_NSE 9
00043 const float fpH[ABEL_NSE] = {
00044     1.000000000000000000f,
00045     0.610926299405048390f,
00046     0.895089852938535935f,
00047     1.34082948787002865f,
00048     2.02532848558443890f,
00049     3.18110895533701843f,
00050     5.90898360396353794f,
00051     77.6000213494180286f,
00052     528.221800846070892f
00053 };
00054 const double dpH[ABEL_NSE] = {
00055     1.000000000000000000,
00056     0.610926299405048390,
00057     0.895089852938535935,
00058     1.34082948787002865,
00059     2.02532848558443890,
00060     3.18110895533701843,
00061     5.90898360396353794,
00062     77.6000213494180286,
00063     528.221800846070892
00064 };
00065 const float fpLambda[ABEL_NSE] = {
00066     0.000000000000000000f,
00067     -2.08424632126539366f,
00068     -5.78928630565552371f,
00069     -14.6268676854951032f,
00070     -35.0617158334443104f,
00071     -83.3258406398958158f,
00072     -210.358805421311445f,
00073     -6673.64911325382036f,
00074     -34897.7050244132261f
00075 };
00076 const double dpLambda[ABEL_NSE] = {
00077     0.000000000000000000,
00078     -2.08424632126539366,
00079     -5.78928630565552371,
00080     -14.6268676854951032,
00081     -35.0617158334443104,
00082     -83.3258406398958158,
00083     -210.358805421311445,
00084     -6673.64911325382036,
00085     -34897.7050244132261
00086 };
00087 
00088 
00089 void clHankel::InitAbel (const float *fpNullPtr)
00090 {
00091     long i, j;
00092     float *a, *b0, *b1, fi, hj, lambdaj, scale, temp;
00093 
00094     a = (float *) A.Size(ABEL_NSE * lSize * sizeof(float));
00095     b0 = (float *) B0.Size(ABEL_NSE * lSize * sizeof(float));
00096     b1 = (float *) B1.Size(ABEL_NSE * lSize * sizeof(float));
00097     for (i = 1; i < lSize; ++i) 
00098     {
00099         fi = i + 1.0f;
00100         for (j = 0; j < ABEL_NSE; ++j) 
00101         {
00102             hj = fpH[j];
00103             lambdaj = fpLambda[j];
00104             a[i * ABEL_NSE + j] = temp = 
00105                 powf(fi / (fi - 1.0f), lambdaj);
00106             temp *= fi / (fi - 1.0f);
00107             scale = 2.0f * hj * (fi - 1.0f) /
00108                 ((lambdaj + 1.0f) * (lambdaj + 2.0f));
00109             b0[i * ABEL_NSE + j] = 
00110                 scale * (fi - 1.0f + (lambdaj + 2.0f - fi) * temp);
00111             b1[i * ABEL_NSE + j] = 
00112                 -scale * (lambdaj + 1.0f + fi - fi * temp);
00113         }
00114     }
00115 }
00116 
00117 
00118 void clHankel::InitAbel (const double *dpNullPtr)
00119 {
00120     long i, j;
00121     double *a, *b0, *b1, fi, hj, lambdaj, scale, temp;
00122 
00123     a = (double *) A.Size(ABEL_NSE * lSize * sizeof(double));
00124     b0 = (double *) B0.Size(ABEL_NSE * lSize * sizeof(double));
00125     b1 = (double *) B1.Size(ABEL_NSE * lSize * sizeof(double));
00126     for (i = 1; i < lSize; ++i)
00127     {
00128         fi = i + 1.0;
00129         for (j = 0; j < ABEL_NSE; ++j)
00130         {
00131             hj = fpH[j];
00132             lambdaj = fpLambda[j];
00133             a[i * ABEL_NSE + j] = temp = 
00134                 pow(fi / (fi - 1.0), lambdaj);
00135             temp *= fi / (fi - 1.0);
00136             scale = 2.0 * hj * (fi - 1.0) /
00137                 ((lambdaj + 1.0) * (lambdaj + 2.0));
00138             b0[i * ABEL_NSE + j] = 
00139                 scale * (fi - 1.0 + (lambdaj + 2.0 - fi) * temp);
00140             b1[i * ABEL_NSE + j] = 
00141                 -scale * (lambdaj + 1.0 + fi - fi * temp);
00142         }
00143     }
00144 }
00145 
00146 
00147 void clHankel::DoAbel (float *fpRes, const float *fpSrc)
00148 {
00149     long i, j;
00150     float sum, fi, fip1;
00151     float *a, *b0, *b1, xi[ABEL_NSE];
00152 
00153     a = (float *) A.GetPtr();
00154     b0 = (float *) B0.GetPtr();
00155     b1 = (float *) B1.GetPtr();
00156     fi = fpSrc[lSize - 1];
00157     fpRes[0] = 0.5f * fpSrc[0] + fi;
00158     sum = 0.0f;
00159     for (j = 0; j < ABEL_NSE; ++j) 
00160     {
00161         xi[j] = b1[(lSize - 1) * ABEL_NSE + j] * fi;
00162         sum += xi[j];
00163     }
00164     fpRes[lSize - 1] = sum;
00165     for (i = lSize - 2; i > 0; --i) 
00166     {
00167         fip1 = fi;
00168         fi = fpSrc[i];
00169         fpRes[0] += fi;
00170         sum = 0.0f;
00171         for (j = 0; j < ABEL_NSE; ++j) 
00172         {
00173             xi[j] = a[i * ABEL_NSE + j] * xi[j] + 
00174                 b0[i * ABEL_NSE + j] * fip1 + 
00175                 b1[i * ABEL_NSE + j] * fi;
00176             sum += xi[j];
00177         }
00178         fpRes[i] = sum;
00179     }
00180     fpRes[0] *= 2.0f;
00181 }
00182 
00183 
00184 void clHankel::DoAbel (double *dpRes, const double *dpSrc)
00185 {
00186     long i, j;
00187     double sum, fi, fip1;
00188     double *a, *b0, *b1, xi[ABEL_NSE];
00189 
00190     a = (double *) A.GetPtr();
00191     b0 = (double *) B0.GetPtr();
00192     b1 = (double *) B1.GetPtr();
00193     fi = dpSrc[lSize - 1];
00194     dpRes[0] = 0.5 * dpSrc[0] + fi;
00195     sum = 0.0;
00196     for (j = 0; j < ABEL_NSE; ++j)
00197     {
00198         xi[j] = b1[(lSize - 1) * ABEL_NSE + j] * fi;
00199         sum += xi[j];
00200     }
00201     dpRes[lSize - 1] = sum;
00202     for (i = lSize - 2; i > 0; --i)
00203     {
00204         fip1 = fi;
00205         fi = dpSrc[i];
00206         dpRes[0] += fi;
00207         sum = 0.0;
00208         for (j = 0; j < ABEL_NSE; ++j)
00209         {
00210             xi[j] = a[i * ABEL_NSE + j] * xi[j] + 
00211                 b0[i * ABEL_NSE + j] * fip1 + 
00212                 b1[i * ABEL_NSE + j] * fi;
00213             sum += xi[j];
00214         }
00215         dpRes[i] = sum;
00216     }
00217     dpRes[0] *= 2.0;
00218 }
00219 
00220 
00221 void clHankel::UninitAbel ()
00222 {
00223     A.Free();
00224     B0.Free();
00225     B1.Free();
00226 }
00227 
00228 
00229 clHankel::clHankel ()
00230 {
00231     lSize = 0;
00232 }
00233 
00234 
00235 clHankel::~clHankel ()
00236 {
00237     if (lSize != 0) Uninitialize();
00238 }
00239 
00240 
00241 void clHankel::Initialize (long lNewSize, const float *fpNullPtr)
00242 {
00243     lSize = lNewSize / 2 + 1;
00244     lFFTSize = lNewSize;
00245     InitAbel(fpNullPtr);
00246     GX.Size(lFFTSize * sizeof(float));
00247     //GK.Size(lSize * sizeof(float) * 2);  // for PFAFFT
00248     GK.Size(lFFTSize * sizeof(stSCplx));  // for "normal" FFT
00249     fOutScale0 = (float) (1.0 / (2.0 * acos(-1.0)));
00250     fOutScale1 = (float) (-1.0 / (2.0 * acos(-1.0)));
00251     DSP.FFTInitialize(lFFTSize, false);
00252 }
00253 
00254 
00255 void clHankel::Initialize (long lNewSize, const double *dpNullPtr)
00256 {
00257     lSize = lNewSize / 2 + 1;
00258     lFFTSize = lNewSize;
00259     InitAbel(dpNullPtr);
00260     GX.Size(lFFTSize * sizeof(double));
00261     //GK.Size(lSize * sizeof(double) * 2);  // for PFAFFT
00262     GK.Size(lFFTSize * sizeof(stDCplx));  // for "normal" FFT
00263     dOutScale0 = 1.0 / (2.0 * acos(-1.0));
00264     dOutScale1 = -1.0 / (2.0 * acos(-1.0));
00265     DSP.FFTInitialize(lFFTSize, false);
00266 }
00267 
00268 
00269 void clHankel::Uninitialize ()
00270 {
00271     UninitAbel();
00272     GX.Free();
00273     GK.Free();
00274     lSize = 0;
00275 }
00276 
00277 
00278 void clHankel::Process0 (float *fpRes, const float *fpSrc)
00279 {
00280     long i;
00281     float fPreScale;
00282     float *gx;
00283     //float *gk;
00284     stpSCplx gk;
00285 #   ifdef __GNUG__
00286     stSCplx spTemp[lFFTSize];
00287 #   else
00288     clDSPAlloc Temp(lFFTSize * sizeof(stSCplx));
00289     stpSCplx spTemp = Temp;
00290 #   endif
00291 
00292     gx = GX;
00293     gk = GK;
00294     DoAbel(gx, fpSrc);
00295     /*for (i = lSize; i < lFFTSize; ++i)
00296         gx[i] = gx[lFFTSize - i];
00297     FFT.pfarc(-1, lFFTSize, gx, gk);
00298     for (i = 0; i < lSize; ++i)
00299         fpRes[i] = fOutScale0 * gk[i << 1];*/
00300     fPreScale = 2.0f / lSize;
00301     for (i = 0; i < (lFFTSize >> 1); i++)
00302     {
00303         spTemp[i].R = gx[i] * fPreScale;
00304         spTemp[i].I = 0;
00305     }
00306     for (i = (lFFTSize >> 1); i < lFFTSize; i++)
00307     {
00308         spTemp[i].R = gx[lFFTSize - i] * fPreScale;
00309         spTemp[i].I = 0;
00310     }
00311     DSP.IFFTo(gk, spTemp);
00312     for (i = 0; i < lSize; i++)
00313     {
00314         fpRes[i] = sqrt(gk[i].R * gk[i].R + gk[i].I * gk[i].I);
00315     }
00316 }
00317 
00318 
00319 void clHankel::Process0 (double *dpRes, const double *dpSrc)
00320 {
00321     long i;
00322     double dPreScale;
00323     double *gx;
00324     //double *gk;
00325     stpDCplx gk;
00326 #   ifdef __GNUG__
00327     stDCplx spTemp[lFFTSize];
00328 #   else
00329     clDSPAlloc Temp(lFFTSize * sizeof(stDCplx));
00330     stpDCplx spTemp = Temp;
00331 #   endif
00332 
00333     gx = GX;
00334     gk = GK;
00335     DoAbel(gx, dpSrc);
00336     /*for (i = lSize; i < lFFTSize; ++i)
00337         gx[i] = gx[lFFTSize - i];
00338     FFT.pfarc(-1, lFFTSize, gx, gk);
00339     for (i = 0; i < lSize; ++i)
00340         dpRes[i] = dOutScale0 * gk[i << 1];*/
00341     dPreScale = 2.0 / lSize;
00342     for (i = 0; i < (lFFTSize >> 1); i++)
00343     {
00344         spTemp[i].R = gx[i] * dPreScale;
00345         spTemp[i].I = 0;
00346     }
00347     for (i = (lFFTSize >> 1); i < lFFTSize; i++)
00348     {
00349         spTemp[i].R = gx[lFFTSize - i] * dPreScale;
00350         spTemp[i].I = 0;
00351     }
00352     DSP.IFFTo(gk, spTemp);
00353     for (i = 0; i < lSize; i++)
00354     {
00355         dpRes[i] = sqrt(gk[i].R * gk[i].R + gk[i].I * gk[i].I);
00356     }
00357 }
00358 
00359 
00360 void clHankel::Process1 (float *fpRes, const float *fpSrc)
00361 {
00362     long i;
00363     float fPreScale;
00364     float *gx;
00365     //float *gk;
00366     stpSCplx gk;
00367 #   ifdef __GNUG__
00368     stSCplx spTemp[lFFTSize];
00369 #   else
00370     clDSPAlloc Temp(lFFTSize * sizeof(stSCplx));
00371     stpSCplx spTemp = Temp;
00372 #   endif
00373 
00374     gx = GX;
00375     gk = GK;
00376     for (i = 1; i < lSize; ++i)
00377         gx[i] = fpSrc[i] / i;
00378     DoAbel(gx, gx);
00379     for (i = 0; i < lSize; ++i)
00380         gx[i] *= i;
00381     for (i = lSize; i < lFFTSize; ++i)
00382         gx[i] = -gx[lFFTSize - i];
00383     gx[lFFTSize / 2] = 0.0f;
00384     /*FFT.pfarc(-1, lFFTSize, gx, gk);
00385     for (i = 0; i < lSize; ++i)
00386         fpRes[i] = fOutScale1 * gk[(i << 1) + 1];*/
00387     fPreScale = 2.0f / lSize;
00388     for (i = 0; i < lFFTSize; i++)
00389     {
00390         spTemp[i].R = gx[i] * fPreScale;
00391         spTemp[i].I = 0;
00392     }
00393     DSP.IFFTo(gk, spTemp);
00394     for (i = 0; i < lSize; i++)
00395     {
00396         fpRes[i] = sqrt(gk[i].R * gk[i].R + gk[i].I * gk[i].I);
00397     }
00398 }
00399 
00400 
00401 void clHankel::Process1 (double *dpRes, const double *dpSrc)
00402 {
00403     long i;
00404     double dPreScale;
00405     double *gx;
00406     //double *gk;
00407     stpDCplx gk;
00408 #   ifdef __GNUG__
00409     stDCplx spTemp[lFFTSize];
00410 #   else
00411     clDSPAlloc Temp(lFFTSize * sizeof(stDCplx));
00412     stpDCplx spTemp = Temp;
00413 #   endif
00414 
00415     gx = GX;
00416     gk = GK;
00417     for (i = 1; i < lSize; ++i)
00418         gx[i] = dpSrc[i] / i;
00419     DoAbel(gx, gx);
00420     for (i = 0; i < lSize; ++i)
00421         gx[i] *= i;
00422     for (i = lSize; i < lFFTSize; ++i)
00423         gx[i] = -gx[lFFTSize - i];
00424     gx[lFFTSize / 2] = 0.0;
00425     /*FFT.pfarc(-1, lFFTSize, gx, gk);
00426     for (i = 0; i < lSize; ++i)
00427         dpRes[i] = dOutScale1 * gk[(i << 1) + 1];*/
00428     dPreScale = 2.0 / lSize;
00429     for (i = 0; i < lFFTSize; i++)
00430     {
00431         spTemp[i].R = gx[i] * dPreScale;
00432         spTemp[i].I = 0;
00433     }
00434     DSP.IFFTo(gk, spTemp);
00435     for (i = 0; i < lSize; i++)
00436     {
00437         dpRes[i] = sqrt(gk[i].R * gk[i].R + gk[i].I * gk[i].I);
00438     }
00439 }

Generated on Tue Mar 2 19:46:44 2004 for libDSP by doxygen 1.3.6