| [394] | 1 | /* | 
|---|
|  | 2 | ** FFT and FHT routines | 
|---|
|  | 3 | **  Copyright 1988, 1993; Ron Mayer | 
|---|
|  | 4 | ** | 
|---|
|  | 5 | **  fht(fz,n); | 
|---|
|  | 6 | **      Does a hartley transform of "n" points in the array "fz". | 
|---|
|  | 7 | **  fft(n,real,imag) | 
|---|
|  | 8 | **      Does a fourier transform of "n" points of the "real" and | 
|---|
|  | 9 | **      "imag" arrays. | 
|---|
|  | 10 | **  ifft(n,real,imag) | 
|---|
|  | 11 | **      Does an inverse fourier transform of "n" points of the "real" | 
|---|
|  | 12 | **      and "imag" arrays. | 
|---|
|  | 13 | **  realfft(n,real) | 
|---|
|  | 14 | **      Does a real-valued fourier transform of "n" points of the | 
|---|
|  | 15 | **      "real" array. The real part of the transform ends | 
|---|
|  | 16 | **      up in the first half of the array and the imaginary part of the | 
|---|
|  | 17 | **      transform ends up in the second half of the array. | 
|---|
|  | 18 | **  realifft(n,real) | 
|---|
|  | 19 | **      The inverse of the realfft() routine above. | 
|---|
|  | 20 | ** | 
|---|
|  | 21 | ** | 
|---|
|  | 22 | ** NOTE: This routine uses at least 2 patented algorithms, and may be | 
|---|
|  | 23 | **       under the restrictions of a bunch of different organizations. | 
|---|
|  | 24 | **       Although I wrote it completely myself; it is kind of a derivative | 
|---|
|  | 25 | **       of a routine I once authored and released under the GPL, so it | 
|---|
|  | 26 | **       may fall under the free software foundation's restrictions; | 
|---|
|  | 27 | **       it was worked on as a Stanford Univ project, so they claim | 
|---|
|  | 28 | **       some rights to it; it was further optimized at work here, so | 
|---|
|  | 29 | **       I think this company claims parts of it.  The patents are | 
|---|
|  | 30 | **       held by R. Bracewell (the FHT algorithm) and O. Buneman (the | 
|---|
|  | 31 | **       trig generator), both at Stanford Univ. | 
|---|
|  | 32 | **       If it were up to me, I'd say go do whatever you want with it; | 
|---|
|  | 33 | **       but it would be polite to give credit to the following people | 
|---|
|  | 34 | **       if you use this anywhere: | 
|---|
|  | 35 | **           Euler     - probable inventor of the fourier transform. | 
|---|
|  | 36 | **           Gauss     - probable inventor of the FFT. | 
|---|
|  | 37 | **           Hartley   - probable inventor of the hartley transform. | 
|---|
|  | 38 | **           Buneman   - for a really cool trig generator | 
|---|
|  | 39 | **           Mayer(me) - for authoring this particular version and | 
|---|
|  | 40 | **                       including all the optimizations in one package. | 
|---|
|  | 41 | **       Thanks, | 
|---|
|  | 42 | **       Ron Mayer; mayer@acuson.com | 
|---|
|  | 43 | ** | 
|---|
|  | 44 | */ | 
|---|
|  | 45 |  | 
|---|
|  | 46 | #include "mayer_fft.h" | 
|---|
|  | 47 |  | 
|---|
|  | 48 | #define GOOD_TRIG | 
|---|
|  | 49 | #include "trigtbl.h" | 
|---|
|  | 50 |  | 
|---|
|  | 51 | char fht_version[] = "Brcwl-Hrtly-Ron-dbld"; | 
|---|
|  | 52 |  | 
|---|
|  | 53 | #define SQRT2_2   0.70710678118654752440084436210484 | 
|---|
|  | 54 | #define SQRT2   2*0.70710678118654752440084436210484 | 
|---|
|  | 55 |  | 
|---|
|  | 56 | void fht(REAL *fz,int n) | 
|---|
|  | 57 | { | 
|---|
|  | 58 | REAL a,b; | 
|---|
|  | 59 | REAL c1,s1,s2,c2,s3,c3,s4,c4; | 
|---|
|  | 60 | REAL f0,g0,f1,g1,f2,g2,f3,g3; | 
|---|
|  | 61 | int i,k,k1,k2,k3,k4,kx; | 
|---|
|  | 62 | REAL *fi,*fn,*gi; | 
|---|
|  | 63 | TRIG_VARS; | 
|---|
|  | 64 |  | 
|---|
|  | 65 | for (k1=1,k2=0;k1<n;k1++) | 
|---|
|  | 66 | { | 
|---|
|  | 67 | REAL a; | 
|---|
|  | 68 | for (k=n>>1; (!((k2^=k)&k)); k>>=1); | 
|---|
|  | 69 | if (k1>k2) | 
|---|
|  | 70 | { | 
|---|
|  | 71 | a=fz[k1];fz[k1]=fz[k2];fz[k2]=a; | 
|---|
|  | 72 | } | 
|---|
|  | 73 | } | 
|---|
|  | 74 | for ( k=0 ; (1<<k)<n ; k++ ); | 
|---|
|  | 75 | k  &= 1; | 
|---|
|  | 76 | if (k==0) | 
|---|
|  | 77 | { | 
|---|
|  | 78 | for (fi=fz,fn=fz+n;fi<fn;fi+=4) | 
|---|
|  | 79 | { | 
|---|
|  | 80 | REAL f0,f1,f2,f3; | 
|---|
|  | 81 | f1     = fi[0 ]-fi[1 ]; | 
|---|
|  | 82 | f0     = fi[0 ]+fi[1 ]; | 
|---|
|  | 83 | f3     = fi[2 ]-fi[3 ]; | 
|---|
|  | 84 | f2     = fi[2 ]+fi[3 ]; | 
|---|
|  | 85 | fi[2 ] = (f0-f2); | 
|---|
|  | 86 | fi[0 ] = (f0+f2); | 
|---|
|  | 87 | fi[3 ] = (f1-f3); | 
|---|
|  | 88 | fi[1 ] = (f1+f3); | 
|---|
|  | 89 | } | 
|---|
|  | 90 | } | 
|---|
|  | 91 | else | 
|---|
|  | 92 | { | 
|---|
|  | 93 | for (fi=fz,fn=fz+n,gi=fi+1;fi<fn;fi+=8,gi+=8) | 
|---|
|  | 94 | { | 
|---|
|  | 95 | REAL s1,c1,s2,c2,s3,c3,s4,c4,g0,f0,f1,g1,f2,g2,f3,g3; | 
|---|
|  | 96 | c1     = fi[0 ] - gi[0 ]; | 
|---|
|  | 97 | s1     = fi[0 ] + gi[0 ]; | 
|---|
|  | 98 | c2     = fi[2 ] - gi[2 ]; | 
|---|
|  | 99 | s2     = fi[2 ] + gi[2 ]; | 
|---|
|  | 100 | c3     = fi[4 ] - gi[4 ]; | 
|---|
|  | 101 | s3     = fi[4 ] + gi[4 ]; | 
|---|
|  | 102 | c4     = fi[6 ] - gi[6 ]; | 
|---|
|  | 103 | s4     = fi[6 ] + gi[6 ]; | 
|---|
|  | 104 | f1     = (s1 - s2); | 
|---|
|  | 105 | f0     = (s1 + s2); | 
|---|
|  | 106 | g1     = (c1 - c2); | 
|---|
|  | 107 | g0     = (c1 + c2); | 
|---|
|  | 108 | f3     = (s3 - s4); | 
|---|
|  | 109 | f2     = (s3 + s4); | 
|---|
|  | 110 | g3     = SQRT2*c4; | 
|---|
|  | 111 | g2     = SQRT2*c3; | 
|---|
|  | 112 | fi[4 ] = f0 - f2; | 
|---|
|  | 113 | fi[0 ] = f0 + f2; | 
|---|
|  | 114 | fi[6 ] = f1 - f3; | 
|---|
|  | 115 | fi[2 ] = f1 + f3; | 
|---|
|  | 116 | gi[4 ] = g0 - g2; | 
|---|
|  | 117 | gi[0 ] = g0 + g2; | 
|---|
|  | 118 | gi[6 ] = g1 - g3; | 
|---|
|  | 119 | gi[2 ] = g1 + g3; | 
|---|
|  | 120 | } | 
|---|
|  | 121 | } | 
|---|
|  | 122 | if (n<16) return; | 
|---|
|  | 123 |  | 
|---|
|  | 124 | do | 
|---|
|  | 125 | { | 
|---|
|  | 126 | REAL s1,c1; | 
|---|
|  | 127 | k  += 2; | 
|---|
|  | 128 | k1  = 1  << k; | 
|---|
|  | 129 | k2  = k1 << 1; | 
|---|
|  | 130 | k4  = k2 << 1; | 
|---|
|  | 131 | k3  = k2 + k1; | 
|---|
|  | 132 | kx  = k1 >> 1; | 
|---|
|  | 133 | fi  = fz; | 
|---|
|  | 134 | gi  = fi + kx; | 
|---|
|  | 135 | fn  = fz + n; | 
|---|
|  | 136 | do | 
|---|
|  | 137 | { | 
|---|
|  | 138 | REAL g0,f0,f1,g1,f2,g2,f3,g3; | 
|---|
|  | 139 | f1      = fi[0 ] - fi[k1]; | 
|---|
|  | 140 | f0      = fi[0 ] + fi[k1]; | 
|---|
|  | 141 | f3      = fi[k2] - fi[k3]; | 
|---|
|  | 142 | f2      = fi[k2] + fi[k3]; | 
|---|
|  | 143 | fi[k2]  = f0         - f2; | 
|---|
|  | 144 | fi[0 ]  = f0         + f2; | 
|---|
|  | 145 | fi[k3]  = f1         - f3; | 
|---|
|  | 146 | fi[k1]  = f1         + f3; | 
|---|
|  | 147 | g1      = gi[0 ] - gi[k1]; | 
|---|
|  | 148 | g0      = gi[0 ] + gi[k1]; | 
|---|
|  | 149 | g3      = SQRT2  * gi[k3]; | 
|---|
|  | 150 | g2      = SQRT2  * gi[k2]; | 
|---|
|  | 151 | gi[k2]  = g0         - g2; | 
|---|
|  | 152 | gi[0 ]  = g0         + g2; | 
|---|
|  | 153 | gi[k3]  = g1         - g3; | 
|---|
|  | 154 | gi[k1]  = g1         + g3; | 
|---|
|  | 155 | gi     += k4; | 
|---|
|  | 156 | fi     += k4; | 
|---|
|  | 157 | } while (fi<fn); | 
|---|
|  | 158 | TRIG_INIT(k,c1,s1); | 
|---|
|  | 159 | for (i=1;i<kx;i++) | 
|---|
|  | 160 | { | 
|---|
|  | 161 | REAL c2,s2; | 
|---|
|  | 162 | TRIG_NEXT(k,c1,s1); | 
|---|
|  | 163 | c2 = c1*c1 - s1*s1; | 
|---|
|  | 164 | s2 = 2*(c1*s1); | 
|---|
|  | 165 | fn = fz + n; | 
|---|
|  | 166 | fi = fz +i; | 
|---|
|  | 167 | gi = fz +k1-i; | 
|---|
|  | 168 | do | 
|---|
|  | 169 | { | 
|---|
|  | 170 | REAL a,b,g0,f0,f1,g1,f2,g2,f3,g3; | 
|---|
|  | 171 | b       = s2*fi[k1] - c2*gi[k1]; | 
|---|
|  | 172 | a       = c2*fi[k1] + s2*gi[k1]; | 
|---|
|  | 173 | f1      = fi[0 ]    - a; | 
|---|
|  | 174 | f0      = fi[0 ]    + a; | 
|---|
|  | 175 | g1      = gi[0 ]    - b; | 
|---|
|  | 176 | g0      = gi[0 ]    + b; | 
|---|
|  | 177 | b       = s2*fi[k3] - c2*gi[k3]; | 
|---|
|  | 178 | a       = c2*fi[k3] + s2*gi[k3]; | 
|---|
|  | 179 | f3      = fi[k2]    - a; | 
|---|
|  | 180 | f2      = fi[k2]    + a; | 
|---|
|  | 181 | g3      = gi[k2]    - b; | 
|---|
|  | 182 | g2      = gi[k2]    + b; | 
|---|
|  | 183 | b       = s1*f2     - c1*g3; | 
|---|
|  | 184 | a       = c1*f2     + s1*g3; | 
|---|
|  | 185 | fi[k2]  = f0        - a; | 
|---|
|  | 186 | fi[0 ]  = f0        + a; | 
|---|
|  | 187 | gi[k3]  = g1        - b; | 
|---|
|  | 188 | gi[k1]  = g1        + b; | 
|---|
|  | 189 | b       = c1*g2     - s1*f3; | 
|---|
|  | 190 | a       = s1*g2     + c1*f3; | 
|---|
|  | 191 | gi[k2]  = g0        - a; | 
|---|
|  | 192 | gi[0 ]  = g0        + a; | 
|---|
|  | 193 | fi[k3]  = f1        - b; | 
|---|
|  | 194 | fi[k1]  = f1        + b; | 
|---|
|  | 195 | gi     += k4; | 
|---|
|  | 196 | fi     += k4; | 
|---|
|  | 197 | } while (fi<fn); | 
|---|
|  | 198 | } | 
|---|
|  | 199 | TRIG_RESET(k,c1,s1); | 
|---|
|  | 200 | } while (k4<n); | 
|---|
|  | 201 | } | 
|---|
|  | 202 |  | 
|---|
|  | 203 |  | 
|---|
|  | 204 | void ifft(int n, double *real, double *imag) | 
|---|
|  | 205 | { | 
|---|
|  | 206 | double a,b,c,d; | 
|---|
|  | 207 | double q,r,s,t; | 
|---|
|  | 208 | int i,j,k; | 
|---|
|  | 209 | fht(real,n); | 
|---|
|  | 210 | fht(imag,n); | 
|---|
|  | 211 | for (i=1,j=n-1,k=n/2;i<k;i++,j--) { | 
|---|
|  | 212 | a = real[i]; b = real[j];  q=a+b; r=a-b; | 
|---|
|  | 213 | c = imag[i]; d = imag[j];  s=c+d; t=c-d; | 
|---|
|  | 214 | imag[i] = (s+r)*0.5;  imag[j] = (s-r)*0.5; | 
|---|
|  | 215 | real[i] = (q-t)*0.5;  real[j] = (q+t)*0.5; | 
|---|
|  | 216 | } | 
|---|
|  | 217 | } | 
|---|
|  | 218 |  | 
|---|
|  | 219 | void realfft(int n, double *real) | 
|---|
|  | 220 | { | 
|---|
|  | 221 | double a,b,c,d; | 
|---|
|  | 222 | int i,j,k; | 
|---|
|  | 223 | fht(real,n); | 
|---|
|  | 224 | for (i=1,j=n-1,k=n/2;i<k;i++,j--) { | 
|---|
|  | 225 | a = real[i]; | 
|---|
|  | 226 | b = real[j]; | 
|---|
|  | 227 | real[j] = (a-b)*0.5; | 
|---|
|  | 228 | real[i] = (a+b)*0.5; | 
|---|
|  | 229 | } | 
|---|
|  | 230 | } | 
|---|
|  | 231 |  | 
|---|
|  | 232 | void fft(int n, double *real,double *imag) | 
|---|
|  | 233 | { | 
|---|
|  | 234 | double a,b,c,d; | 
|---|
|  | 235 | double q,r,s,t; | 
|---|
|  | 236 | int i,j,k; | 
|---|
|  | 237 | for (i=1,j=n-1,k=n/2;i<k;i++,j--) { | 
|---|
|  | 238 | a = real[i]; b = real[j];  q=a+b; r=a-b; | 
|---|
|  | 239 | c = imag[i]; d = imag[j];  s=c+d; t=c-d; | 
|---|
|  | 240 | real[i] = (q+t)*.5; real[j] = (q-t)*.5; | 
|---|
|  | 241 | imag[i] = (s-r)*.5; imag[j] = (s+r)*.5; | 
|---|
|  | 242 | } | 
|---|
|  | 243 | fht(real,n); | 
|---|
|  | 244 | fht(imag,n); | 
|---|
|  | 245 | } | 
|---|
|  | 246 |  | 
|---|
|  | 247 | void realifft(int n,double *real) | 
|---|
|  | 248 | { | 
|---|
|  | 249 | double a,b,c,d; | 
|---|
|  | 250 | int i,j,k; | 
|---|
|  | 251 | for (i=1,j=n-1,k=n/2;i<k;i++,j--) { | 
|---|
|  | 252 | a = real[i]; | 
|---|
|  | 253 | b = real[j]; | 
|---|
|  | 254 | real[j] = (a-b); | 
|---|
|  | 255 | real[i] = (a+b); | 
|---|
|  | 256 | } | 
|---|
|  | 257 | fht(real,n); | 
|---|
|  | 258 | } | 
|---|