├── Makefile ├── README ├── bluestein.h ├── c_utils.c ├── fftpack.h ├── c_utils.h ├── bluestein.c ├── ffttest.c ├── ls_fft.h ├── ls_fft.c ├── fftpack_inc.c └── fftpack.c /Makefile: -------------------------------------------------------------------------------- 1 | CC:= gcc 2 | CFLAGS:= -O2 -W -Wall -std=c89 -ansi -pedantic 3 | 4 | LIBSRC:= c_utils.c ls_fft.c fftpack.c bluestein.c 5 | LIBOBJ:=$(LIBSRC:%.c=%.o) 6 | 7 | %.o : %.c 8 | $(CC) $(CFLAGS) -c $< 9 | 10 | default: libfftpack.a 11 | 12 | $(LIBOBJ): *.h fftpack_inc.c 13 | 14 | libfftpack.a: $(LIBOBJ) 15 | ar crv libfftpack.a $(LIBOBJ) 16 | 17 | ffttest: libfftpack.a ffttest.o 18 | $(CC) $(CFLAGS) ffttest.o libfftpack.a -o ffttest -lm 19 | 20 | test: ffttest 21 | ./ffttest 22 | 23 | clean: 24 | rm -f *.o ffttest libfftpack.a 25 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ls_fft description: 2 | 3 | This package is intended to calculate one-dimensional real or complex FFTs 4 | with high accuracy and good efficiency even for lengths containing large 5 | prime factors. 6 | 7 | Before any FFT is executed, a plan must be generated for it. Plan creation 8 | is designed to be fast, so that there is no significant overhead if the 9 | plan is only used once or a few times. 10 | 11 | The main component of the code is based on Paul N. Swarztrauber's FFTPACK in the 12 | double precision incarnation by Hugh C. Pumphrey 13 | (http://www.netlib.org/fftpack/dp.tgz). 14 | 15 | I replaced the iterative sine and cosine calculations in radfg() and radbg() 16 | by an exact calculation, which slightly improves the transform accuracy for 17 | real FFTs with lengths containing large prime factors. 18 | 19 | Since FFTPACK becomes quite slow for FFT lengths with large prime factors 20 | (in the worst case of prime lengths it reaches O(n*n) complexity), I 21 | implemented Bluestein's algorithm, which computes a FFT of length n by 22 | several FFTs of length n2>=2*n-1 and a convolution. Since n2 can be chosen 23 | to be highly composite, this algorithm is more efficient if n has large 24 | prime factors. The longer FFTs themselves are then computed using the FFTPACK 25 | routines. 26 | Bluestein's algorithm was implemented according to the description at 27 | http://en.wikipedia.org/wiki/Bluestein's_FFT_algorithm. 28 | 29 | Thread-safety: 30 | All routines can be called concurrently; all information needed by ls_fft 31 | is stored in the plan variable. However, using the same plan variable on 32 | multiple threads simultaneously is not supported and will lead to data 33 | corruption. 34 | -------------------------------------------------------------------------------- /bluestein.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005-2011, Max-Planck-Society 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the Max-Planck-Society nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE MAX-PLANCK-SOCIETY BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * libfftpack is being developed at the Max-Planck-Institut fuer Astrophysik 30 | * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt 31 | * (DLR). 32 | */ 33 | 34 | /* 35 | * \author Martin Reinecke 36 | */ 37 | 38 | #ifndef PLANCK_BLUESTEIN_H 39 | #define PLANCK_BLUESTEIN_H 40 | 41 | #include "c_utils.h" 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | size_t prime_factor_sum (size_t n); 48 | 49 | void bluestein_i (size_t n, double **tstorage, size_t *worksize); 50 | void bluestein (size_t n, double *data, double *tstorage, int isign); 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /c_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2011, Max-Planck-Society 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the Max-Planck-Society nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE MAX-PLANCK-SOCIETY BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * libc_utils is being developed at the Max-Planck-Institut fuer Astrophysik 30 | * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt 31 | * (DLR). 32 | */ 33 | 34 | /* 35 | * Convenience functions 36 | * 37 | * Author: Martin Reinecke 38 | */ 39 | 40 | #include 41 | #include 42 | #include 43 | #include "c_utils.h" 44 | 45 | void util_fail_ (const char *file, int line, const char *func, const char *msg) 46 | { 47 | fprintf(stderr,"%s, %i (%s):\n%s\n",file,line,func,msg); 48 | exit(1); 49 | } 50 | void util_warn_ (const char *file, int line, const char *func, const char *msg) 51 | { 52 | fprintf(stderr,"%s, %i (%s):\n%s\n",file,line,func,msg); 53 | exit(1); 54 | } 55 | 56 | void *util_malloc_ (size_t sz) 57 | { 58 | void *res; 59 | if (sz==0) return NULL; 60 | res = malloc(sz); 61 | UTIL_ASSERT(res,"malloc() failed"); 62 | return res; 63 | } 64 | void util_free_ (void *ptr) 65 | { if ((ptr)!=NULL) free(ptr); } 66 | -------------------------------------------------------------------------------- /fftpack.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010-2011, Max-Planck-Society 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the Max-Planck-Society nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE MAX-PLANCK-SOCIETY BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * libfftpack is being developed at the Max-Planck-Institut fuer Astrophysik 30 | * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt 31 | * (DLR). 32 | */ 33 | 34 | /* 35 | fftpack.h : function declarations for fftpack.c 36 | Algorithmically based on Fortran-77 FFTPACK by Paul N. Swarztrauber 37 | (Version 4, 1985). 38 | 39 | C port by Martin Reinecke (2010) 40 | */ 41 | 42 | #ifndef PLANCK_FFTPACK_H 43 | #define PLANCK_FFTPACK_H 44 | 45 | #include "c_utils.h" 46 | 47 | #ifdef __cplusplus 48 | extern "C" { 49 | #endif 50 | 51 | /*! forward complex transform */ 52 | void cfftf(size_t N, double complex_data[], double wrk[]); 53 | /*! backward complex transform */ 54 | void cfftb(size_t N, double complex_data[], double wrk[]); 55 | /*! initializer for complex transforms */ 56 | void cffti(size_t N, double wrk[]); 57 | 58 | /*! forward real transform */ 59 | void rfftf(size_t N, double data[], double wrk[]); 60 | /*! backward real transform */ 61 | void rfftb(size_t N, double data[], double wrk[]); 62 | /*! initializer for real transforms */ 63 | void rffti(size_t N, double wrk[]); 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /c_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2011, Max-Planck-Society 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the Max-Planck-Society nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE MAX-PLANCK-SOCIETY BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * libc_utils is being developed at the Max-Planck-Institut fuer Astrophysik 30 | * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt 31 | * (DLR). 32 | */ 33 | 34 | /*! \file c_utils.h 35 | * Convenience functions 36 | * 37 | * \author Martin Reinecke 38 | * \note This file should only be included from .c files, NOT from .h files. 39 | */ 40 | 41 | #ifndef PLANCK_C_UTILS_H 42 | #define PLANCK_C_UTILS_H 43 | 44 | #include 45 | #include 46 | #include 47 | 48 | #ifdef __cplusplus 49 | extern "C" { 50 | #endif 51 | 52 | void util_fail_ (const char *file, int line, const char *func, const char *msg); 53 | void util_warn_ (const char *file, int line, const char *func, const char *msg); 54 | void *util_malloc_ (size_t sz); 55 | void util_free_ (void *ptr); 56 | 57 | void announce_c (const char *name); 58 | void module_startup_c (const char *name, int argc, int argc_expected, 59 | const char *argv_expected, int verbose); 60 | 61 | #if defined (__GNUC__) 62 | #define UTIL_FUNC_NAME__ __func__ 63 | #else 64 | #define UTIL_FUNC_NAME__ "unknown" 65 | #endif 66 | 67 | #define UTIL_ASSERT(cond,msg) \ 68 | if(!(cond)) util_fail_(__FILE__,__LINE__,UTIL_FUNC_NAME__,msg) 69 | #define UTIL_WARN(cond,msg) \ 70 | if(!(cond)) util_warn_(__FILE__,__LINE__,UTIL_FUNC_NAME__,msg) 71 | #define UTIL_FAIL(msg) \ 72 | util_fail_(__FILE__,__LINE__,UTIL_FUNC_NAME__,msg) 73 | 74 | #define ALLOC(ptr,type,num) \ 75 | do { (ptr)=(type *)util_malloc_((num)*sizeof(type)); } while (0) 76 | #define RALLOC(type,num) \ 77 | ((type *)util_malloc_((num)*sizeof(type))) 78 | #define DEALLOC(ptr) \ 79 | do { util_free_(ptr); (ptr)=NULL; } while(0) 80 | #define RESIZE(ptr,type,num) \ 81 | do { util_free_(ptr); ALLOC(ptr,type,num); } while(0) 82 | #define REALLOC(ptr,type,num) \ 83 | do { \ 84 | ptr = (type *)realloc(ptr,(num)*sizeof(type)); \ 85 | UTIL_ASSERT(ptr,"realloc() failed"); \ 86 | } while(0) 87 | #define GROW(ptr,type,sz_old,sz_new) \ 88 | do { \ 89 | if ((sz_new)>(sz_old)) \ 90 | { RESIZE(ptr,type,2*(sz_new));sz_old=2*(sz_new); } \ 91 | } while(0) 92 | #define SET_ARRAY(ptr,i1,i2,val) \ 93 | do { \ 94 | ptrdiff_t cnt_; \ 95 | for (cnt_=(i1);cnt_<(i2);++cnt_) (ptr)[cnt_]=(val); \ 96 | } while(0) 97 | #define COPY_ARRAY(src,dest,i1,i2) \ 98 | do { \ 99 | ptrdiff_t cnt_; \ 100 | for (cnt_=(i1);cnt_<(i2);++cnt_) (dest)[cnt_]=(src)[cnt_]; \ 101 | } while(0) 102 | 103 | #define ALLOC2D(ptr,type,num1,num2) \ 104 | do { \ 105 | size_t cnt_, num1_=(num1), num2_=(num2); \ 106 | ALLOC(ptr,type *,num1_); \ 107 | ALLOC(ptr[0],type,num1_*num2_); \ 108 | for (cnt_=1; cnt_(b)) ? (a) : (b)) 120 | #define IMIN(a,b) \ 121 | (((a)<(b)) ? (a) : (b)) 122 | 123 | #define SWAP(a,b,type) \ 124 | do { type tmp_=(a); (a)=(b); (b)=tmp_; } while(0) 125 | 126 | #define CHECK_STACK_ALIGN(align) \ 127 | do { \ 128 | double foo; \ 129 | UTIL_WARN((((size_t)(&foo))&(align-1))==0, \ 130 | "WARNING: stack not sufficiently aligned!"); \ 131 | } while(0) 132 | 133 | #ifdef __cplusplus 134 | } 135 | #endif 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /bluestein.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005-2011, Max-Planck-Society 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the Max-Planck-Society nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE MAX-PLANCK-SOCIETY BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * libfftpack is being developed at the Max-Planck-Institut fuer Astrophysik 30 | * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt 31 | * (DLR). 32 | */ 33 | 34 | /* 35 | * \author Martin Reinecke 36 | */ 37 | 38 | #include 39 | #include 40 | #include "fftpack.h" 41 | #include "bluestein.h" 42 | 43 | /* returns the sum of all prime factors of n */ 44 | size_t prime_factor_sum (size_t n) 45 | { 46 | size_t result=0,x,limit,tmp; 47 | while (((tmp=(n>>1))<<1)==n) 48 | { result+=2; n=tmp; } 49 | 50 | limit=(size_t)sqrt(n+0.01); 51 | for (x=3; x<=limit; x+=2) 52 | while ((tmp=(n/x))*x==n) 53 | { 54 | result+=x; 55 | n=tmp; 56 | limit=(size_t)sqrt(n+0.01); 57 | } 58 | if (n>1) result+=n; 59 | 60 | return result; 61 | } 62 | 63 | /* returns the smallest composite of 2, 3 and 5 which is >= n */ 64 | static size_t good_size(size_t n) 65 | { 66 | size_t f2, f23, f235, bestfac=2*n; 67 | if (n<=6) return n; 68 | 69 | for (f2=1; f2=n) bestfac=f235; 73 | return bestfac; 74 | } 75 | 76 | void bluestein_i (size_t n, double **tstorage, size_t *worksize) 77 | { 78 | static const double pi=3.14159265358979323846; 79 | size_t n2=good_size(n*2-1); 80 | size_t m, coeff; 81 | double angle, xn2; 82 | double *bk, *bkf, *work; 83 | double pibyn=pi/n; 84 | *worksize=2+2*n+8*n2+16; 85 | *tstorage = RALLOC(double,2+2*n+8*n2+16); 86 | ((size_t *)(*tstorage))[0]=n2; 87 | bk = *tstorage+2; 88 | bkf = *tstorage+2+2*n; 89 | work= *tstorage+2+2*(n+n2); 90 | 91 | /* initialize b_k */ 92 | bk[0] = 1; 93 | bk[1] = 0; 94 | 95 | coeff=0; 96 | for (m=1; m=2*n) coeff-=2*n; 100 | angle = pibyn*coeff; 101 | bk[2*m] = cos(angle); 102 | bk[2*m+1] = sin(angle); 103 | } 104 | 105 | /* initialize the zero-padded, Fourier transformed b_k. Add normalisation. */ 106 | xn2 = 1./n2; 107 | bkf[0] = bk[0]*xn2; 108 | bkf[1] = bk[1]*xn2; 109 | for (m=2; m<2*n; m+=2) 110 | { 111 | bkf[m] = bkf[2*n2-m] = bk[m] *xn2; 112 | bkf[m+1] = bkf[2*n2-m+1] = bk[m+1] *xn2; 113 | } 114 | for (m=2*n;m<=(2*n2-2*n+1);++m) 115 | bkf[m]=0.; 116 | cffti (n2,work); 117 | cfftf (n2,bkf,work); 118 | } 119 | 120 | void bluestein (size_t n, double *data, double *tstorage, int isign) 121 | { 122 | size_t n2=*((size_t *)tstorage); 123 | size_t m; 124 | double *bk, *bkf, *akf, *work; 125 | bk = tstorage+2; 126 | bkf = tstorage+2+2*n; 127 | work= tstorage+2+2*(n+n2); 128 | akf = tstorage+2+2*n+6*n2+16; 129 | 130 | /* initialize a_k and FFT it */ 131 | if (isign>0) 132 | for (m=0; m<2*n; m+=2) 133 | { 134 | akf[m] = data[m]*bk[m] - data[m+1]*bk[m+1]; 135 | akf[m+1] = data[m]*bk[m+1] + data[m+1]*bk[m]; 136 | } 137 | else 138 | for (m=0; m<2*n; m+=2) 139 | { 140 | akf[m] = data[m]*bk[m] + data[m+1]*bk[m+1]; 141 | akf[m+1] =-data[m]*bk[m+1] + data[m+1]*bk[m]; 142 | } 143 | for (m=2*n; m<2*n2; ++m) 144 | akf[m]=0; 145 | 146 | cfftf (n2,akf,work); 147 | 148 | /* do the convolution */ 149 | if (isign>0) 150 | for (m=0; m<2*n2; m+=2) 151 | { 152 | double im = -akf[m]*bkf[m+1] + akf[m+1]*bkf[m]; 153 | akf[m ] = akf[m]*bkf[m] + akf[m+1]*bkf[m+1]; 154 | akf[m+1] = im; 155 | } 156 | else 157 | for (m=0; m<2*n2; m+=2) 158 | { 159 | double im = akf[m]*bkf[m+1] + akf[m+1]*bkf[m]; 160 | akf[m ] = akf[m]*bkf[m] - akf[m+1]*bkf[m+1]; 161 | akf[m+1] = im; 162 | } 163 | 164 | 165 | /* inverse FFT */ 166 | cfftb (n2,akf,work); 167 | 168 | /* multiply by b_k* */ 169 | if (isign>0) 170 | for (m=0; m<2*n; m+=2) 171 | { 172 | data[m] = bk[m] *akf[m] - bk[m+1]*akf[m+1]; 173 | data[m+1] = bk[m+1]*akf[m] + bk[m] *akf[m+1]; 174 | } 175 | else 176 | for (m=0; m<2*n; m+=2) 177 | { 178 | data[m] = bk[m] *akf[m] + bk[m+1]*akf[m+1]; 179 | data[m+1] =-bk[m+1]*akf[m] + bk[m] *akf[m+1]; 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /ffttest.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2004-2011, Max-Planck-Society 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the Max-Planck-Society nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE MAX-PLANCK-SOCIETY BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * libfftpack is being developed at the Max-Planck-Institut fuer Astrophysik 30 | * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt 31 | * (DLR). 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #include "fftpack.h" 39 | #include "ls_fft.h" 40 | #include "bluestein.h" 41 | 42 | #define maxlen 4096 43 | 44 | static void fill_random (double *data, double *odata, size_t length) 45 | { 46 | size_t m; 47 | for (m=0; mepsilon) printf("problem at real length %i: %e\n",length,err); 97 | } 98 | for (length=1; length<=maxlen; ++length) 99 | { 100 | fill_random (data, odata, length); 101 | plan = make_real_plan (length); 102 | real_plan_forward_fftpack (plan, data); 103 | real_plan_backward_fftpack (plan, data); 104 | normalize (data, length, length); 105 | kill_real_plan (plan); 106 | err = errcalc (data, odata, length); 107 | if (err>epsilon) printf("problem at real length %i: %e\n",length,err); 108 | } 109 | for (length=1; length<=maxlen; ++length) 110 | { 111 | fill_random (data, odata, length); 112 | plan = make_real_plan (length); 113 | real_plan_forward_fftw (plan, data); 114 | real_plan_backward_fftw (plan, data); 115 | normalize (data, length, length); 116 | kill_real_plan (plan); 117 | err = errcalc (data, odata, length); 118 | if (err>epsilon) printf("problem at real length %i: %e\n",length,err); 119 | } 120 | for (length=1; length<=maxlen; ++length) 121 | { 122 | fill_random (data, odata, length); 123 | plan = make_real_plan (length); 124 | real_plan_forward_fftw (plan, data); 125 | halfcomplex2fftpack (data,plan->length); 126 | real_plan_backward_fftpack (plan, data); 127 | normalize (data, length, length); 128 | kill_real_plan (plan); 129 | err = errcalc (data, odata, length); 130 | if (err>epsilon) printf("problem at real length %i: %e\n",length,err); 131 | } 132 | for (length=1; length<=maxlen; ++length) 133 | { 134 | fill_random (data, odata, length); 135 | plan = make_real_plan (length); 136 | real_plan_forward_fftpack (plan, data); 137 | fftpack2halfcomplex (data,plan->length); 138 | real_plan_backward_fftw (plan, data); 139 | normalize (data, length, length); 140 | kill_real_plan (plan); 141 | err = errcalc (data, odata, length); 142 | if (err>epsilon) printf("problem at real length %i: %e\n",length,err); 143 | } 144 | } 145 | 146 | static void test_complex(void) 147 | { 148 | double data[2*maxlen], odata[2*maxlen]; 149 | int length; 150 | double err; 151 | const double epsilon=3e-15; 152 | complex_plan plan; 153 | for (length=1; length<=maxlen; ++length) 154 | { 155 | fill_random (data, odata, 2*length); 156 | plan = make_complex_plan (length); 157 | complex_plan_forward(plan, data); 158 | complex_plan_backward(plan, data); 159 | normalize (data, 2*length, length); 160 | kill_complex_plan (plan); 161 | err = errcalc (data, odata, 2*length); 162 | if (err>epsilon) printf("problem at complex length %i: %e\n",length,err); 163 | } 164 | } 165 | 166 | int main(void) 167 | { 168 | test_real(); 169 | test_complex(); 170 | return 0; 171 | } 172 | -------------------------------------------------------------------------------- /ls_fft.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2004-2011, Max-Planck-Society 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the Max-Planck-Society nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE MAX-PLANCK-SOCIETY BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * libfftpack is being developed at the Max-Planck-Institut fuer Astrophysik 30 | * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt 31 | * (DLR). 32 | */ 33 | 34 | /*! \file ls_fft.h 35 | * Interface for the LevelS FFT package. 36 | * 37 | * \author Martin Reinecke 38 | */ 39 | 40 | #ifndef PLANCK_LS_FFT_H 41 | #define PLANCK_LS_FFT_H 42 | 43 | #include "c_utils.h" 44 | 45 | #ifdef __cplusplus 46 | extern "C" { 47 | #endif 48 | 49 | /*!\defgroup fftgroup FFT interface 50 | This package is intended to calculate one-dimensional real or complex FFTs 51 | with high accuracy and good efficiency even for lengths containing large 52 | prime factors. 53 | 54 | Before any FFT is executed, a plan must be generated for it. Plan creation 55 | is designed to be fast, so that there is no significant overhead if the 56 | plan is only used once or a few times. 57 | 58 | The main component of the code is based on Paul N. Swarztrauber's FFTPACK in the 59 | double precision incarnation by Hugh C. Pumphrey 60 | (http://www.netlib.org/fftpack/dp.tgz). 61 | 62 | I replaced the iterative sine and cosine calculations in radfg() and radbg() 63 | by an exact calculation, which slightly improves the transform accuracy for 64 | real FFTs with lengths containing large prime factors. 65 | 66 | Since FFTPACK becomes quite slow for FFT lengths with large prime factors 67 | (in the worst case of prime lengths it reaches \f$\mathcal{O}(n^2)\f$ 68 | complexity), I implemented Bluestein's algorithm, which computes a FFT of length 69 | \f$n\f$ by several FFTs of length \f$n_2\ge 2n-1\f$ and a convolution. Since 70 | \f$n_2\f$ can be chosen to be highly composite, this algorithm is more efficient 71 | if \f$n\f$ has large prime factors. The longer FFTs themselves are then computed 72 | using the FFTPACK routines. 73 | Bluestein's algorithm was implemented according to the description on Wikipedia 74 | ( 75 | http://en.wikipedia.org/wiki/Bluestein%27s_FFT_algorithm). 76 | 77 | \b Thread-safety: 78 | All routines can be called concurrently; all information needed by 79 | ls_fft is stored in the plan variable. However, using the same plan 80 | variable on multiple threads simultaneously is not supported and will lead to 81 | data corruption. 82 | */ 83 | /*! \{ */ 84 | 85 | typedef struct 86 | { 87 | double *work; 88 | size_t length, worksize; 89 | int bluestein; 90 | } complex_plan_i; 91 | 92 | /*! The opaque handle type for complex-FFT plans. */ 93 | typedef complex_plan_i * complex_plan; 94 | 95 | /*! Returns a plan for a complex FFT with \a length elements. */ 96 | complex_plan make_complex_plan (size_t length); 97 | /*! Constructs a copy of \a plan. */ 98 | complex_plan copy_complex_plan (complex_plan plan); 99 | /*! Destroys a plan for a complex FFT. */ 100 | void kill_complex_plan (complex_plan plan); 101 | /*! Computes a complex forward FFT on \a data, using \a plan. 102 | \a Data has the form r0, i0, r1, i1, ..., 103 | r[length-1], i[length-1]. */ 104 | void complex_plan_forward (complex_plan plan, double *data); 105 | /*! Computes a complex backward FFT on \a data, using \a plan. 106 | \a Data has the form r0, i0, r1, i1, ..., 107 | r[length-1], i[length-1]. */ 108 | void complex_plan_backward (complex_plan plan, double *data); 109 | 110 | typedef struct 111 | { 112 | double *work; 113 | size_t length, worksize; 114 | int bluestein; 115 | } real_plan_i; 116 | 117 | /*! The opaque handle type for real-FFT plans. */ 118 | typedef real_plan_i * real_plan; 119 | 120 | /*! Returns a plan for a real FFT with \a length elements. */ 121 | real_plan make_real_plan (size_t length); 122 | /*! Constructs a copy of \a plan. */ 123 | real_plan copy_real_plan (real_plan plan); 124 | /*! Destroys a plan for a real FFT. */ 125 | void kill_real_plan (real_plan plan); 126 | /*! Computes a real forward FFT on \a data, using \a plan 127 | and assuming the FFTPACK storage scheme: 128 | - on entry, \a data has the form r0, r1, ..., r[length-1]; 129 | - on exit, it has the form r0, r1, i1, r2, i2, ... 130 | (a total of \a length values). */ 131 | void real_plan_forward_fftpack (real_plan plan, double *data); 132 | /*! Computes a real forward FFT on \a data, using \a plan 133 | and assuming the FFTPACK storage scheme: 134 | - on entry, \a data has the form r0, r1, i1, r2, i2, ... 135 | (a total of \a length values); 136 | - on exit, it has the form r0, r1, ..., r[length-1]. */ 137 | void real_plan_backward_fftpack (real_plan plan, double *data); 138 | /*! Computes a real forward FFT on \a data, using \a plan 139 | and assuming the FFTW halfcomplex storage scheme: 140 | - on entry, \a data has the form r0, r1, ..., r[length-1]; 141 | - on exit, it has the form r0, r1, r2, ..., i2, i1. */ 142 | void real_plan_forward_fftw (real_plan plan, double *data); 143 | /*! Computes a real backward FFT on \a data, using \a plan 144 | and assuming the FFTW halfcomplex storage scheme: 145 | - on entry, \a data has the form r0, r1, r2, ..., i2, i1. 146 | - on exit, it has the form r0, r1, ..., r[length-1]. */ 147 | void real_plan_backward_fftw (real_plan plan, double *data); 148 | /*! Computes a real forward FFT on \a data, using \a plan 149 | and assuming a full-complex storage scheme: 150 | - on entry, \a data has the form r0, [ignored], r1, [ignored], ..., 151 | r[length-1], [ignored]; 152 | - on exit, it has the form r0, i0, r1, i1, ..., 153 | r[length-1], i[length-1]. 154 | */ 155 | void real_plan_forward_c (real_plan plan, double *data); 156 | /*! Computes a real backward FFT on \a data, using \a plan 157 | and assuming a full-complex storage scheme: 158 | - on entry, \a data has the form r0, i0, r1, i1, ..., 159 | r[length-1], i[length-1]; 160 | - on exit, it has the form r0, 0, r1, 0, ..., r[length-1], 0. */ 161 | void real_plan_backward_c (real_plan plan, double *data); 162 | 163 | void fftpack2halfcomplex (double *data, size_t n); 164 | void halfcomplex2fftpack (double *data, size_t n); 165 | 166 | /*! \} */ 167 | 168 | #ifdef __cplusplus 169 | } 170 | #endif 171 | 172 | #endif 173 | -------------------------------------------------------------------------------- /ls_fft.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005-2011, Max-Planck-Society 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the Max-Planck-Society nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE MAX-PLANCK-SOCIETY BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * libfftpack is being developed at the Max-Planck-Institut fuer Astrophysik 30 | * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt 31 | * (DLR). 32 | */ 33 | 34 | /* 35 | * \author Martin Reinecke 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | #include "bluestein.h" 42 | #include "fftpack.h" 43 | #include "ls_fft.h" 44 | 45 | complex_plan make_complex_plan (size_t length) 46 | { 47 | complex_plan plan = RALLOC(complex_plan_i,1); 48 | size_t pfsum = prime_factor_sum(length); 49 | double comp1 = (double)(length*pfsum); 50 | double comp2 = 2*3*length*log(3.*length); 51 | comp2*=3.; /* fudge factor that appears to give good overall performance */ 52 | plan->length=length; 53 | plan->bluestein = (comp2bluestein) 55 | bluestein_i (length,&(plan->work),&(plan->worksize)); 56 | else 57 | { 58 | plan->worksize=4*length+15; 59 | plan->work=RALLOC(double,4*length+15); 60 | cffti(length, plan->work); 61 | } 62 | return plan; 63 | } 64 | 65 | complex_plan copy_complex_plan (complex_plan plan) 66 | { 67 | if (!plan) return NULL; 68 | { 69 | complex_plan newplan = RALLOC(complex_plan_i,1); 70 | *newplan = *plan; 71 | newplan->work=RALLOC(double,newplan->worksize); 72 | memcpy(newplan->work,plan->work,sizeof(double)*newplan->worksize); 73 | return newplan; 74 | } 75 | } 76 | 77 | void kill_complex_plan (complex_plan plan) 78 | { 79 | DEALLOC(plan->work); 80 | DEALLOC(plan); 81 | } 82 | 83 | void complex_plan_forward (complex_plan plan, double *data) 84 | { 85 | if (plan->bluestein) 86 | bluestein (plan->length, data, plan->work, -1); 87 | else 88 | cfftf (plan->length, data, plan->work); 89 | } 90 | 91 | void complex_plan_backward (complex_plan plan, double *data) 92 | { 93 | if (plan->bluestein) 94 | bluestein (plan->length, data, plan->work, 1); 95 | else 96 | cfftb (plan->length, data, plan->work); 97 | } 98 | 99 | 100 | real_plan make_real_plan (size_t length) 101 | { 102 | real_plan plan = RALLOC(real_plan_i,1); 103 | size_t pfsum = prime_factor_sum(length); 104 | double comp1 = .5*length*pfsum; 105 | double comp2 = 2*3*length*log(3.*length); 106 | comp2*=3; /* fudge factor that appears to give good overall performance */ 107 | plan->length=length; 108 | plan->bluestein = (comp2bluestein) 110 | bluestein_i (length,&(plan->work),&(plan->worksize)); 111 | else 112 | { 113 | plan->worksize=2*length+15; 114 | plan->work=RALLOC(double,2*length+15); 115 | rffti(length, plan->work); 116 | } 117 | return plan; 118 | } 119 | 120 | real_plan copy_real_plan (real_plan plan) 121 | { 122 | if (!plan) return NULL; 123 | { 124 | real_plan newplan = RALLOC(real_plan_i,1); 125 | *newplan = *plan; 126 | newplan->work=RALLOC(double,newplan->worksize); 127 | memcpy(newplan->work,plan->work,sizeof(double)*newplan->worksize); 128 | return newplan; 129 | } 130 | } 131 | 132 | void kill_real_plan (real_plan plan) 133 | { 134 | DEALLOC(plan->work); 135 | DEALLOC(plan); 136 | } 137 | 138 | void real_plan_forward_fftpack (real_plan plan, double *data) 139 | { 140 | if (plan->bluestein) 141 | { 142 | size_t m; 143 | size_t n=plan->length; 144 | double *tmp = RALLOC(double,2*n); 145 | for (m=0; mwork,-1); 151 | data[0] = tmp[0]; 152 | memcpy (data+1, tmp+2, (n-1)*sizeof(double)); 153 | DEALLOC(tmp); 154 | } 155 | else 156 | rfftf (plan->length, data, plan->work); 157 | } 158 | 159 | void fftpack2halfcomplex (double *data, size_t n) 160 | { 161 | size_t m; 162 | double *tmp = RALLOC(double,n); 163 | tmp[0]=data[0]; 164 | for (m=1; m<(n+1)/2; ++m) 165 | { 166 | tmp[m]=data[2*m-1]; 167 | tmp[n-m]=data[2*m]; 168 | } 169 | if (!(n&1)) 170 | tmp[n/2]=data[n-1]; 171 | memcpy (data,tmp,n*sizeof(double)); 172 | DEALLOC(tmp); 173 | } 174 | 175 | void halfcomplex2fftpack (double *data, size_t n) 176 | { 177 | size_t m; 178 | double *tmp = RALLOC(double,n); 179 | tmp[0]=data[0]; 180 | for (m=1; m<(n+1)/2; ++m) 181 | { 182 | tmp[2*m-1]=data[m]; 183 | tmp[2*m]=data[n-m]; 184 | } 185 | if (!(n&1)) 186 | tmp[n-1]=data[n/2]; 187 | memcpy (data,tmp,n*sizeof(double)); 188 | DEALLOC(tmp); 189 | } 190 | 191 | void real_plan_forward_fftw (real_plan plan, double *data) 192 | { 193 | real_plan_forward_fftpack (plan, data); 194 | fftpack2halfcomplex (data,plan->length); 195 | } 196 | 197 | void real_plan_backward_fftpack (real_plan plan, double *data) 198 | { 199 | if (plan->bluestein) 200 | { 201 | size_t m; 202 | size_t n=plan->length; 203 | double *tmp = RALLOC(double,2*n); 204 | tmp[0]=data[0]; 205 | tmp[1]=0.; 206 | memcpy (tmp+2,data+1, (n-1)*sizeof(double)); 207 | if ((n&1)==0) tmp[n+1]=0.; 208 | for (m=2; mwork, 1); 214 | for (m=0; mlength, data, plan->work); 220 | } 221 | 222 | void real_plan_backward_fftw (real_plan plan, double *data) 223 | { 224 | halfcomplex2fftpack (data,plan->length); 225 | real_plan_backward_fftpack (plan, data); 226 | } 227 | 228 | void real_plan_forward_c (real_plan plan, double *data) 229 | { 230 | size_t m; 231 | size_t n=plan->length; 232 | 233 | if (plan->bluestein) 234 | { 235 | for (m=1; m<2*n; m+=2) 236 | data[m]=0; 237 | bluestein (plan->length, data, plan->work, -1); 238 | data[1]=0; 239 | for (m=2; mwork); 255 | data[0] = data[1]; 256 | data[1] = 0; 257 | for (m=2; mlength; 269 | 270 | if (plan->bluestein) 271 | { 272 | size_t m; 273 | data[1]=0; 274 | for (m=2; mlength, data, plan->work, 1); 285 | for (m=1; m<2*n; m+=2) 286 | data[m]=0; 287 | } 288 | else 289 | { 290 | ptrdiff_t m; 291 | data[1] = data[0]; 292 | rfftb (n, data+1, plan->work); 293 | for (m=n-1; m>=0; --m) 294 | { 295 | data[2*m] = data[m+1]; 296 | data[2*m+1] = 0.; 297 | } 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /fftpack_inc.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010-2011, Max-Planck-Society 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the Max-Planck-Society nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE MAX-PLANCK-SOCIETY BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * libfftpack is being developed at the Max-Planck-Institut fuer Astrophysik 30 | * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt 31 | * (DLR). 32 | */ 33 | 34 | /* 35 | fftpack.c : A set of FFT routines in C. 36 | Algorithmically based on Fortran-77 FFTPACK by Paul N. Swarztrauber 37 | (Version 4, 1985). 38 | 39 | C port by Martin Reinecke (2010) 40 | */ 41 | 42 | #ifdef BACKWARD 43 | #define PSIGN + 44 | #define PMSIGNC(a,b,c,d) { a.r=c.r+d.r; a.i=c.i+d.i; b.r=c.r-d.r; b.i=c.i-d.i; } 45 | /* a = b*c */ 46 | #define MULPMSIGNC(a,b,c) { a.r=b.r*c.r-b.i*c.i; a.i=b.r*c.i+b.i*c.r; } 47 | #else 48 | #define PSIGN - 49 | #define PMSIGNC(a,b,c,d) { a.r=c.r-d.r; a.i=c.i-d.i; b.r=c.r+d.r; b.i=c.i+d.i; } 50 | /* a = conj(b)*c */ 51 | #define MULPMSIGNC(a,b,c) { a.r=b.r*c.r+b.i*c.i; a.i=b.r*c.i-b.i*c.r; } 52 | #endif 53 | 54 | static void X(2) (size_t ido, size_t l1, const cmplx *cc, cmplx *ch, 55 | const cmplx *wa) 56 | { 57 | const size_t cdim=2; 58 | size_t k,i; 59 | cmplx t; 60 | if (ido==1) 61 | for (k=0;kip) iang-=ip; 284 | abr.r += ccl[l ].r*wal[iang].r; 285 | abr.i += ccl[l ].i*wal[iang].r; 286 | abi.r += ccl[lc].r*wal[iang].i; 287 | abi.i += ccl[lc].i*wal[iang].i; 288 | } 289 | #ifndef BACKWARD 290 | { abi.i=-abi.i; abi.r=-abi.r; } 291 | #endif 292 | CONJFLIPC(abi) 293 | PMC(CH(i,k,j),CH(i,k,jc),abr,abi) 294 | } 295 | } 296 | 297 | DEALLOC(tarr); 298 | 299 | if (ido==1) return; 300 | 301 | for (j=1; j 43 | #include 44 | #include 45 | #include "fftpack.h" 46 | 47 | #define WA(x,i) wa[(i)+(x)*ido] 48 | #define CH(a,b,c) ch[(a)+ido*((b)+l1*(c))] 49 | #define CC(a,b,c) cc[(a)+ido*((b)+cdim*(c))] 50 | #define PM(a,b,c,d) { a=c+d; b=c-d; } 51 | #define PMC(a,b,c,d) { a.r=c.r+d.r; a.i=c.i+d.i; b.r=c.r-d.r; b.i=c.i-d.i; } 52 | #define ADDC(a,b,c) { a.r=b.r+c.r; a.i=b.i+c.i; } 53 | #define SCALEC(a,b) { a.r*=b; a.i*=b; } 54 | #define CONJFLIPC(a) { double tmp_=a.r; a.r=-a.i; a.i=tmp_; } 55 | /* (a+ib) = conj(c+id) * (e+if) */ 56 | #define MULPM(a,b,c,d,e,f) { a=c*e+d*f; b=c*f-d*e; } 57 | 58 | typedef struct { 59 | double r,i; 60 | } cmplx; 61 | 62 | #define CONCAT(a,b) a ## b 63 | 64 | #define X(arg) CONCAT(passb,arg) 65 | #define BACKWARD 66 | #include "fftpack_inc.c" 67 | #undef BACKWARD 68 | #undef X 69 | 70 | #define X(arg) CONCAT(passf,arg) 71 | #include "fftpack_inc.c" 72 | #undef X 73 | 74 | #undef CC 75 | #undef CH 76 | #define CC(a,b,c) cc[(a)+ido*((b)+l1*(c))] 77 | #define CH(a,b,c) ch[(a)+ido*((b)+cdim*(c))] 78 | 79 | static void radf2 (size_t ido, size_t l1, const double *cc, double *ch, 80 | const double *wa) 81 | { 82 | const size_t cdim=2; 83 | size_t i, k, ic; 84 | double ti2, tr2; 85 | 86 | for (k=0; k=2*ip) aidx-=2*ip; 301 | ar2=csarr[aidx]; 302 | ai2=csarr[aidx+1]; 303 | for(ik=0; ik=2*ip) aidx-=2*ip; 569 | ar2=csarr[aidx]; 570 | ai2=csarr[aidx+1]; 571 | for(ik=0; ik0) ? passb4(ido, l1, p1, p2, wa+iw) 632 | : passf4(ido, l1, p1, p2, wa+iw); 633 | else if(ip==2) 634 | (isign>0) ? passb2(ido, l1, p1, p2, wa+iw) 635 | : passf2(ido, l1, p1, p2, wa+iw); 636 | else if(ip==3) 637 | (isign>0) ? passb3(ido, l1, p1, p2, wa+iw) 638 | : passf3(ido, l1, p1, p2, wa+iw); 639 | else if(ip==5) 640 | (isign>0) ? passb5(ido, l1, p1, p2, wa+iw) 641 | : passf5(ido, l1, p1, p2, wa+iw); 642 | else if(ip==6) 643 | (isign>0) ? passb6(ido, l1, p1, p2, wa+iw) 644 | : passf6(ido, l1, p1, p2, wa+iw); 645 | else 646 | (isign>0) ? passbg(ido, ip, l1, p1, p2, wa+iw) 647 | : passfg(ido, ip, l1, p1, p2, wa+iw); 648 | SWAP(p1,p2,cmplx *); 649 | l1=l2; 650 | iw+=(ip-1)*ido; 651 | } 652 | if (p1!=c) 653 | memcpy (c,p1,n*sizeof(cmplx)); 654 | } 655 | 656 | void cfftf(size_t n, double c[], double wsave[]) 657 | { 658 | if (n!=1) 659 | cfft1(n, (cmplx*)c, (cmplx*)wsave, (cmplx*)(wsave+2*n), 660 | (size_t*)(wsave+4*n),-1); 661 | } 662 | 663 | void cfftb(size_t n, double c[], double wsave[]) 664 | { 665 | if (n!=1) 666 | cfft1(n, (cmplx*)c, (cmplx*)wsave, (cmplx*)(wsave+2*n), 667 | (size_t*)(wsave+4*n),+1); 668 | } 669 | 670 | static void factorize (size_t n, const size_t *pf, size_t npf, size_t *ifac) 671 | { 672 | size_t nl=n, nf=0, ntry=0, j=0, i; 673 | 674 | startloop: 675 | j++; 676 | ntry = (j<=npf) ? pf[j-1] : ntry+2; 677 | do 678 | { 679 | size_t nq=nl / ntry; 680 | size_t nr=nl-ntry*nq; 681 | if (nr!=0) 682 | goto startloop; 683 | nf++; 684 | ifac[nf+1]=ntry; 685 | nl=nq; 686 | if ((ntry==2) && (nf!=1)) 687 | { 688 | for (i=nf+1; i>2; --i) 689 | ifac[i]=ifac[i-1]; 690 | ifac[2]=2; 691 | } 692 | } 693 | while(nl!=1); 694 | ifac[0]=n; 695 | ifac[1]=nf; 696 | } 697 | 698 | static void cffti1(size_t n, double wa[], size_t ifac[]) 699 | { 700 | static const size_t ntryh[5]={4,6,3,2,5}; 701 | static const double twopi=6.28318530717958647692; 702 | size_t j, k, fi; 703 | 704 | double argh=twopi/n; 705 | size_t i=0, l1=1; 706 | factorize (n,ntryh,5,ifac); 707 | for(k=1; k<=ifac[1]; k++) 708 | { 709 | size_t ip=ifac[k+1]; 710 | size_t ido=n/(l1*ip); 711 | for(j=1; j6) 725 | { 726 | wa[is ]=wa[i ]; 727 | wa[is+1]=wa[i+1]; 728 | } 729 | } 730 | l1*=ip; 731 | } 732 | } 733 | 734 | void cffti(size_t n, double wsave[]) 735 | { if (n!=1) cffti1(n, wsave+2*n,(size_t*)(wsave+4*n)); } 736 | 737 | 738 | /*---------------------------------------------------------------------- 739 | rfftf1, rfftb1, rfftf, rfftb, rffti1, rffti. Real FFTs. 740 | ----------------------------------------------------------------------*/ 741 | 742 | static void rfftf1(size_t n, double c[], double ch[], const double wa[], 743 | const size_t ifac[]) 744 | { 745 | size_t k1, l1=n, nf=ifac[1], iw=n-1; 746 | double *p1=ch, *p2=c; 747 | 748 | for(k1=1; k1<=nf;++k1) 749 | { 750 | size_t ip=ifac[nf-k1+2]; 751 | size_t ido=n / l1; 752 | l1 /= ip; 753 | iw-=(ip-1)*ido; 754 | SWAP (p1,p2,double *); 755 | if(ip==4) 756 | radf4(ido, l1, p1, p2, wa+iw); 757 | else if(ip==2) 758 | radf2(ido, l1, p1, p2, wa+iw); 759 | else if(ip==3) 760 | radf3(ido, l1, p1, p2, wa+iw); 761 | else if(ip==5) 762 | radf5(ido, l1, p1, p2, wa+iw); 763 | else 764 | { 765 | if (ido==1) 766 | SWAP (p1,p2,double *); 767 | radfg(ido, ip, l1, ido*l1, p1, p2, wa+iw); 768 | SWAP (p1,p2,double *); 769 | } 770 | } 771 | if (p1==c) 772 | memcpy (c,ch,n*sizeof(double)); 773 | } 774 | 775 | static void rfftb1(size_t n, double c[], double ch[], const double wa[], 776 | const size_t ifac[]) 777 | { 778 | size_t k1, l1=1, nf=ifac[1], iw=0; 779 | double *p1=c, *p2=ch; 780 | 781 | for(k1=1; k1<=nf; k1++) 782 | { 783 | size_t ip = ifac[k1+1], 784 | ido= n/(ip*l1); 785 | if(ip==4) 786 | radb4(ido, l1, p1, p2, wa+iw); 787 | else if(ip==2) 788 | radb2(ido, l1, p1, p2, wa+iw); 789 | else if(ip==3) 790 | radb3(ido, l1, p1, p2, wa+iw); 791 | else if(ip==5) 792 | radb5(ido, l1, p1, p2, wa+iw); 793 | else 794 | { 795 | radbg(ido, ip, l1, ido*l1, p1, p2, wa+iw); 796 | if (ido!=1) 797 | SWAP (p1,p2,double *); 798 | } 799 | SWAP (p1,p2,double *); 800 | l1*=ip; 801 | iw+=(ip-1)*ido; 802 | } 803 | if (p1!=c) 804 | memcpy (c,ch,n*sizeof(double)); 805 | } 806 | 807 | void rfftf(size_t n, double r[], double wsave[]) 808 | { if(n!=1) rfftf1(n, r, wsave, wsave+n,(size_t*)(wsave+2*n)); } 809 | 810 | void rfftb(size_t n, double r[], double wsave[]) 811 | { if(n!=1) rfftb1(n, r, wsave, wsave+n,(size_t*)(wsave+2*n)); } 812 | 813 | static void rffti1(size_t n, double wa[], size_t ifac[]) 814 | { 815 | static const size_t ntryh[4]={4,2,3,5}; 816 | static const double twopi=6.28318530717958647692; 817 | size_t i, j, k, fi; 818 | 819 | double argh=twopi/n; 820 | size_t is=0, l1=1; 821 | factorize (n,ntryh,4,ifac); 822 | for (k=1; k