| [710] | 1 | #include "fftpserver.h" | 
|---|
|  | 2 | #include "fftpackc.h" | 
|---|
|  | 3 |  | 
|---|
|  | 4 | #include <iostream.h> | 
|---|
|  | 5 |  | 
|---|
|  | 6 |  | 
|---|
| [896] | 7 | /*! | 
|---|
|  | 8 | \class SOPHYA::FFTPackServer | 
|---|
| [710] | 9 | A class that calculates Fourier transforms forwards and backwards. | 
|---|
|  | 10 |  | 
|---|
|  | 11 | The class calls the c library ``fftpack'', which is accessible and documented | 
|---|
|  | 12 | at http://www.netlib.org/fftpack/.  However, the class functions do not | 
|---|
|  | 13 | necessarily correspond with the equivalent fftpack function.  For example, | 
|---|
|  | 14 | fftpack "forward" transformations are in fact inverse fourier transformations. | 
|---|
|  | 15 | Otherwise, the output is in the fftpack format. | 
|---|
|  | 16 |  | 
|---|
|  | 17 |  | 
|---|
|  | 18 | Due to the way that fftpack manages | 
|---|
|  | 19 | its work arrays, an object can run faster if the length of the input arrays | 
|---|
|  | 20 | does not change.  For example, if you need to do a series of FFT's | 
|---|
|  | 21 | of differing length, it may be more efficient to create an fftserver object | 
|---|
|  | 22 | for each length. | 
|---|
|  | 23 | */ | 
|---|
|  | 24 |  | 
|---|
| [896] | 25 | /* \fn virtual void FFTServer::fftf(int l, r_4* inout) | 
|---|
| [710] | 26 | \param l length of array | 
|---|
|  | 27 | \param inout input array /output forward FFT (original array destroyed) | 
|---|
|  | 28 | */ | 
|---|
| [717] | 29 | /*! \fn virtual void FFTServer::fftb(int l, r_4* inout) | 
|---|
| [710] | 30 | \param l length of array | 
|---|
|  | 31 | \param inout input array /output backward FFT (original array destroyed) | 
|---|
|  | 32 | */ | 
|---|
| [896] | 33 | /* \fn virtual void FFTServer::fftf(int l, r_8* inout) | 
|---|
| [710] | 34 | \param l length of array | 
|---|
|  | 35 | \param inout input array /output forward FFT (original array destroyed) | 
|---|
|  | 36 | \param inout input/output array (original array destroyed) | 
|---|
|  | 37 | */ | 
|---|
| [896] | 38 | /* \fn virtual void FFTServer::fftb(int l, r_8* inout) | 
|---|
| [710] | 39 | \param l length of array | 
|---|
|  | 40 | \param inout input array /output backward FFT(original array destroyed) | 
|---|
|  | 41 | */ | 
|---|
| [896] | 42 | /*\fn  virtual void FFTServer::fftf(int l, complex<r_4>* inout) | 
|---|
| [710] | 43 | \param l length of array | 
|---|
|  | 44 | \param inout input array /output forward FFT (original array destroyed) | 
|---|
|  | 45 | */ | 
|---|
| [896] | 46 | /* \fn virtual void FFTServer::fftb(int l, complex<r_4>* inout) | 
|---|
| [710] | 47 | \param l length of array | 
|---|
|  | 48 | \param inout input array /output backward FFT (original array destroyed) | 
|---|
|  | 49 | */ | 
|---|
| [896] | 50 | /* \fn virtual void FFTServer::fftf(int l, complex<r_8>* inout) | 
|---|
| [710] | 51 | \param l length of array | 
|---|
|  | 52 | \param inout input array /output forward FFT (original array destroyed) | 
|---|
|  | 53 | */ | 
|---|
| [896] | 54 | /* \fn virtual void FFTServer::fftb(int l, complex<r_8>* inout) | 
|---|
| [710] | 55 | \param l length of array | 
|---|
|  | 56 | \param inout input array /output backward FFT(original array destroyed) | 
|---|
|  | 57 | */ | 
|---|
| [896] | 58 | /*\fn  virtual void FFTServer::fftf(Vector& in, Vector& out) | 
|---|
| [710] | 59 | \param in input array | 
|---|
|  | 60 | \param out forward FFT | 
|---|
|  | 61 | */ | 
|---|
| [896] | 62 | /* \fn virtual void FFTServer::fftb(Vector& in, Vector& out) | 
|---|
| [710] | 63 | \param in input array | 
|---|
|  | 64 | \param out backward FFT | 
|---|
|  | 65 | */ | 
|---|
|  | 66 |  | 
|---|
|  | 67 | FFTPackServer::FFTPackServer() | 
|---|
| [717] | 68 | : FFTServerInterface("FFTPackServer using extended FFTPack (C-version) package") | 
|---|
| [710] | 69 |  | 
|---|
|  | 70 | { | 
|---|
|  | 71 | sz_rfft = 0;     //the working array and its size for the different | 
|---|
|  | 72 | ws_rfft = NULL;  //possible numerical types | 
|---|
|  | 73 | sz_cfft = 0; | 
|---|
|  | 74 | ws_cfft = NULL; | 
|---|
|  | 75 | sz_cdfft = 0; | 
|---|
|  | 76 | ws_cdfft = NULL; | 
|---|
|  | 77 | } | 
|---|
|  | 78 |  | 
|---|
|  | 79 | FFTPackServer::~FFTPackServer() | 
|---|
|  | 80 | { | 
|---|
|  | 81 | if (ws_rfft) delete[] ws_rfft; | 
|---|
|  | 82 | if (ws_cfft) delete[] ws_cfft; | 
|---|
|  | 83 | if (ws_cdfft) delete[] ws_cdfft; | 
|---|
|  | 84 | } | 
|---|
|  | 85 |  | 
|---|
|  | 86 | FFTServerInterface * FFTPackServer::Clone() | 
|---|
|  | 87 | { | 
|---|
|  | 88 | return (new FFTPackServer); | 
|---|
|  | 89 | } | 
|---|
|  | 90 |  | 
|---|
| [717] | 91 |  | 
|---|
| [710] | 92 | void FFTPackServer::FFTForward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out) | 
|---|
|  | 93 | { | 
|---|
|  | 94 | out = in; | 
|---|
|  | 95 | fftf(out.NElts(), out.Data()); | 
|---|
| [717] | 96 | if (getNormalize()) out *= (1./(r_8)(in.NElts())); | 
|---|
| [710] | 97 | } | 
|---|
|  | 98 |  | 
|---|
|  | 99 | void FFTPackServer::FFTBackward(TVector< complex<r_8> > const & in, TVector< complex<r_8> > & out) | 
|---|
|  | 100 | { | 
|---|
|  | 101 | out = in; | 
|---|
|  | 102 | fftb(out.NElts(), out.Data()); | 
|---|
|  | 103 | } | 
|---|
|  | 104 |  | 
|---|
| [717] | 105 |  | 
|---|
|  | 106 |  | 
|---|
| [710] | 107 | void FFTPackServer::FFTForward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out) | 
|---|
|  | 108 | { | 
|---|
|  | 109 | out = in; | 
|---|
|  | 110 | fftf(out.NElts(), out.Data()); | 
|---|
| [717] | 111 | if (getNormalize()) out *= (1./(r_4)(in.NElts())); | 
|---|
| [710] | 112 | } | 
|---|
|  | 113 |  | 
|---|
|  | 114 | void FFTPackServer::FFTBackward(TVector< complex<r_4> > const & in, TVector< complex<r_4> > & out) | 
|---|
|  | 115 | { | 
|---|
|  | 116 | out = in; | 
|---|
|  | 117 | fftb(out.NElts(), out.Data()); | 
|---|
|  | 118 | } | 
|---|
|  | 119 |  | 
|---|
|  | 120 | void FFTPackServer::FFTForward(TVector< r_4 > const & in, TVector< complex<r_4> > & out) | 
|---|
|  | 121 | { | 
|---|
|  | 122 | TVector< r_4 > inout(in); | 
|---|
|  | 123 | fftf(inout.NElts(), inout.Data()); | 
|---|
|  | 124 | ReShapetoCompl(inout, out); | 
|---|
| [717] | 125 | if (getNormalize()) out *= (1./(r_4)(in.NElts())); | 
|---|
| [710] | 126 | } | 
|---|
|  | 127 |  | 
|---|
|  | 128 | void FFTPackServer::FFTBackward(TVector< complex<r_4> > const & in, TVector< r_4 > & out) | 
|---|
|  | 129 | { | 
|---|
|  | 130 | ReShapetoReal(in, out); | 
|---|
|  | 131 | fftb(out.NElts(), out.Data()); | 
|---|
|  | 132 | } | 
|---|
|  | 133 |  | 
|---|
| [717] | 134 |  | 
|---|
| [710] | 135 | void FFTPackServer::FFTForward(TVector< r_8 > const & in, TVector< complex<r_8> > & out) | 
|---|
|  | 136 | { | 
|---|
|  | 137 | TVector< r_8 > inout(in); | 
|---|
|  | 138 | fftf(inout.NElts(), inout.Data()); | 
|---|
|  | 139 | ReShapetoCompl(inout, out); | 
|---|
| [717] | 140 | if (getNormalize()) out *= (1./(r_8)(in.NElts())); | 
|---|
| [710] | 141 | } | 
|---|
|  | 142 |  | 
|---|
|  | 143 | void FFTPackServer::FFTBackward(TVector< complex<r_8> > const & in, TVector< r_8 > & out) | 
|---|
|  | 144 | { | 
|---|
|  | 145 | ReShapetoReal(in, out); | 
|---|
|  | 146 | fftb(out.NElts(), out.Data()); | 
|---|
|  | 147 | } | 
|---|
|  | 148 |  | 
|---|
| [717] | 149 |  | 
|---|
| [710] | 150 |  | 
|---|
| [791] | 151 | void FFTPackServer::checkint_rfft(int_4 l) | 
|---|
| [710] | 152 | { | 
|---|
|  | 153 | if (sz_rfft == l) return;       //checkint functions check and reallocate | 
|---|
|  | 154 | //memory for the work arrays when performing | 
|---|
|  | 155 | if (ws_rfft) delete[] ws_rfft;  //a transform | 
|---|
|  | 156 | sz_rfft = l; | 
|---|
| [717] | 157 | ws_rfft = new r_4[2*l+15]; | 
|---|
| [710] | 158 | rffti_(&l, ws_rfft); | 
|---|
|  | 159 | } | 
|---|
|  | 160 |  | 
|---|
| [791] | 161 | void FFTPackServer::checkint_cfft(int_4 l) | 
|---|
| [710] | 162 | { | 
|---|
|  | 163 | if (sz_cfft == l) return; | 
|---|
|  | 164 |  | 
|---|
|  | 165 | if (ws_cfft) delete[] ws_cfft; | 
|---|
|  | 166 | sz_cfft = l; | 
|---|
| [717] | 167 | ws_cfft = new r_4[4*l+15]; | 
|---|
| [710] | 168 | cffti_(&l, ws_cfft); | 
|---|
|  | 169 | } | 
|---|
|  | 170 |  | 
|---|
| [791] | 171 | void FFTPackServer::checkint_dfft(int_4 l) | 
|---|
| [710] | 172 | { | 
|---|
|  | 173 | if (sz_dfft == l) return; | 
|---|
|  | 174 |  | 
|---|
|  | 175 | if (ws_dfft) delete[] ws_dfft; | 
|---|
|  | 176 | sz_dfft = l; | 
|---|
| [717] | 177 | ws_dfft = new r_8[2*l+15]; | 
|---|
| [710] | 178 | dffti_(&l, ws_dfft); | 
|---|
|  | 179 | } | 
|---|
|  | 180 |  | 
|---|
| [791] | 181 | void FFTPackServer::checkint_cdfft(int_4 l) | 
|---|
| [710] | 182 | { | 
|---|
|  | 183 | if (sz_cdfft == l) return; | 
|---|
|  | 184 |  | 
|---|
|  | 185 | if (ws_cdfft) delete[] ws_cdfft; | 
|---|
|  | 186 | sz_cdfft = l; | 
|---|
| [717] | 187 | ws_cdfft = new r_8[4*l+15]; | 
|---|
| [710] | 188 | cdffti_(&l, ws_cdfft); | 
|---|
|  | 189 | } | 
|---|
|  | 190 |  | 
|---|
|  | 191 | /* In general forward transformations are resorted since fftpack functions | 
|---|
|  | 192 | return inverse transformations */ | 
|---|
|  | 193 |  | 
|---|
| [791] | 194 | void FFTPackServer::fftf(int_4 l, r_4* inout) | 
|---|
| [710] | 195 | { | 
|---|
|  | 196 | checkint_rfft(l); | 
|---|
|  | 197 | rfftf_(&l, inout, ws_rfft); | 
|---|
| [717] | 198 | //  for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2]; | 
|---|
| [710] | 199 | } | 
|---|
|  | 200 |  | 
|---|
| [791] | 201 | void FFTPackServer::fftf(int_4 l, r_8* inout) | 
|---|
| [710] | 202 | { | 
|---|
|  | 203 | checkint_dfft(l); | 
|---|
|  | 204 | dfftf_(&l, inout, ws_dfft); | 
|---|
| [717] | 205 | //  for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2]; | 
|---|
| [710] | 206 | } | 
|---|
|  | 207 |  | 
|---|
| [791] | 208 | void FFTPackServer::fftf(int_4 l, complex<r_4>* inout) | 
|---|
| [710] | 209 | { | 
|---|
|  | 210 | checkint_cfft(l); | 
|---|
| [717] | 211 | cfftf_(&l, (r_4 *)(inout), ws_cfft); | 
|---|
| [710] | 212 | } | 
|---|
|  | 213 |  | 
|---|
| [791] | 214 | void FFTPackServer::fftf(int_4 l, complex<r_8>* inout) | 
|---|
| [710] | 215 | { | 
|---|
|  | 216 | checkint_cdfft(l); | 
|---|
| [717] | 217 | cdfftf_(&l, (r_8*)(inout), ws_cdfft); | 
|---|
| [710] | 218 | } | 
|---|
|  | 219 |  | 
|---|
| [791] | 220 | void FFTPackServer::fftb(int_4 l, r_4* inout) | 
|---|
| [710] | 221 | { | 
|---|
|  | 222 | checkint_rfft(l); | 
|---|
| [717] | 223 | rfftb_(&l, inout, ws_rfft); | 
|---|
| [710] | 224 | } | 
|---|
|  | 225 |  | 
|---|
| [791] | 226 | void FFTPackServer::fftb(int_4 l, r_8* inout) | 
|---|
| [710] | 227 | { | 
|---|
|  | 228 | checkint_dfft(l); | 
|---|
| [717] | 229 | dfftb_(&l, inout, ws_dfft); | 
|---|
| [710] | 230 | } | 
|---|
|  | 231 |  | 
|---|
| [791] | 232 | void FFTPackServer::fftb(int_4 l, complex<r_4>* inout) | 
|---|
| [710] | 233 | { | 
|---|
|  | 234 | checkint_cfft(l); | 
|---|
| [717] | 235 | cfftb_(&l, (r_4 *)(inout), ws_cfft); | 
|---|
| [710] | 236 | } | 
|---|
|  | 237 |  | 
|---|
| [791] | 238 | void FFTPackServer::fftb(int_4 l, complex<r_8>* inout) | 
|---|
| [710] | 239 | { | 
|---|
|  | 240 | checkint_cdfft(l); | 
|---|
| [717] | 241 | cdfftb_(&l, (r_8 *)(inout), ws_cdfft); | 
|---|
|  | 242 | } | 
|---|
|  | 243 |  | 
|---|
|  | 244 | // Methodes pour reordonner les donnees | 
|---|
|  | 245 |  | 
|---|
|  | 246 | /* --Methode-- */ | 
|---|
|  | 247 | void FFTPackServer::ReShapetoReal( TVector< complex<r_8> > const & in, TVector< r_8 >  & out) | 
|---|
|  | 248 | { | 
|---|
|  | 249 | int n = in.NElts(); | 
|---|
|  | 250 | int ncs = (fabs(in(n-1).imag()) > 1.e-12) ? ncs = 2*n-1 : ncs = n*2-2; | 
|---|
|  | 251 | out.ReSize(ncs); | 
|---|
|  | 252 | int k; | 
|---|
|  | 253 | out(0) = in(0).real(); | 
|---|
|  | 254 | for(k=1;k<n-1;k++) { | 
|---|
|  | 255 | out(2*k-1) = in(k).real(); | 
|---|
|  | 256 | out(2*k) = in(k).imag(); | 
|---|
| [710] | 257 | } | 
|---|
| [717] | 258 | if (ncs == n*2-2)  out(ncs-1) = in(n-1).real(); | 
|---|
|  | 259 | else { out(ncs-2) = in(n-1).real();  out(ncs-1) = in(n-1).imag(); } | 
|---|
| [710] | 260 | } | 
|---|
|  | 261 |  | 
|---|
| [717] | 262 | /* --Methode-- */ | 
|---|
|  | 263 | void FFTPackServer::ReShapetoReal( TVector< complex<r_4> > const & in, TVector< r_4 >  & out) | 
|---|
|  | 264 | { | 
|---|
|  | 265 | int n = in.NElts(); | 
|---|
|  | 266 | int ncs = (fabs(in(n-1).imag()) > 1.e-12) ? ncs = 2*n-1 : ncs = n*2-2; | 
|---|
|  | 267 | out.ReSize(ncs); | 
|---|
|  | 268 | int k; | 
|---|
|  | 269 | out(0) = in(0).real(); | 
|---|
|  | 270 | for(k=1;k<n-1;k++) { | 
|---|
|  | 271 | out(2*k-1) = in(k).real(); | 
|---|
|  | 272 | out(2*k) = in(k).imag(); | 
|---|
|  | 273 | } | 
|---|
|  | 274 | if (ncs == n*2-2)  out(ncs-1) = in(n-1).real(); | 
|---|
|  | 275 | else { out(ncs-2) = in(n-1).real();  out(ncs-1) = in(n-1).imag(); } | 
|---|
|  | 276 | } | 
|---|
|  | 277 |  | 
|---|
|  | 278 |  | 
|---|
|  | 279 | /* --Methode-- */ | 
|---|
|  | 280 | void FFTPackServer::ReShapetoCompl(TVector< r_8 > const & in, TVector< complex<r_8> > & out) | 
|---|
|  | 281 | { | 
|---|
|  | 282 | uint_4 n =  in.NElts(); | 
|---|
|  | 283 | uint_4 ncs = n/2+1; | 
|---|
|  | 284 | uint_4 nc = (n%2 != 0) ? n/2+1 : n/2; | 
|---|
|  | 285 | out.ReSize(ncs); | 
|---|
|  | 286 | out(0) = complex<r_8> (in(0),0.); | 
|---|
|  | 287 | for(int k=1;k<nc;k++) | 
|---|
|  | 288 | out(k) =  complex<r_4> (in(2*k-1), in(2*k)); | 
|---|
|  | 289 | if (n%2 == 0) out(ncs-1) = complex<r_8>(in(n-1), 0.); | 
|---|
|  | 290 |  | 
|---|
|  | 291 | } | 
|---|
|  | 292 |  | 
|---|
|  | 293 | /* --Methode-- */ | 
|---|
|  | 294 | void FFTPackServer::ReShapetoCompl(TVector< r_4 > const & in, TVector< complex<r_4> > & out) | 
|---|
|  | 295 | { | 
|---|
|  | 296 | uint_4 n =  in.NElts(); | 
|---|
|  | 297 | uint_4 ncs = n/2+1; | 
|---|
|  | 298 | uint_4 nc = (n%2 != 0) ? n/2+1 : n/2; | 
|---|
|  | 299 | out.ReSize(ncs); | 
|---|
|  | 300 | out(0) = complex<r_4> (in(0),0.); | 
|---|
|  | 301 | for(int k=1;k<nc;k++) | 
|---|
|  | 302 | out(k) =  complex<r_4> (in(2*k-1), in(2*k)); | 
|---|
|  | 303 | if (n%2 == 0) out(ncs-1) = complex<r_4>(in(n-1), 0.); | 
|---|
|  | 304 | } | 
|---|