annotate ext/kissfft/_kiss_fft_guts.h @ 184:76ec2365b250

Bring in kissfft into this repo (formerly a subrepo, but the remote is not responding)
author Chris Cannam
date Tue, 21 Jul 2015 07:34:15 +0100
parents
children
rev   line source
Chris@184 1 /*
Chris@184 2 Copyright (c) 2003-2010, Mark Borgerding
Chris@184 3
Chris@184 4 All rights reserved.
Chris@184 5
Chris@184 6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Chris@184 7
Chris@184 8 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Chris@184 9 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Chris@184 10 * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
Chris@184 11
Chris@184 12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Chris@184 13 */
Chris@184 14
Chris@184 15 /* kiss_fft.h
Chris@184 16 defines kiss_fft_scalar as either short or a float type
Chris@184 17 and defines
Chris@184 18 typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
Chris@184 19 #include "kiss_fft.h"
Chris@184 20 #include <limits.h>
Chris@184 21
Chris@184 22 #define MAXFACTORS 32
Chris@184 23 /* e.g. an fft of length 128 has 4 factors
Chris@184 24 as far as kissfft is concerned
Chris@184 25 4*4*4*2
Chris@184 26 */
Chris@184 27
Chris@184 28 struct kiss_fft_state{
Chris@184 29 int nfft;
Chris@184 30 int inverse;
Chris@184 31 int factors[2*MAXFACTORS];
Chris@184 32 kiss_fft_cpx twiddles[1];
Chris@184 33 };
Chris@184 34
Chris@184 35 /*
Chris@184 36 Explanation of macros dealing with complex math:
Chris@184 37
Chris@184 38 C_MUL(m,a,b) : m = a*b
Chris@184 39 C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
Chris@184 40 C_SUB( res, a,b) : res = a - b
Chris@184 41 C_SUBFROM( res , a) : res -= a
Chris@184 42 C_ADDTO( res , a) : res += a
Chris@184 43 * */
Chris@184 44 #ifdef FIXED_POINT
Chris@184 45 #if (FIXED_POINT==32)
Chris@184 46 # define FRACBITS 31
Chris@184 47 # define SAMPPROD int64_t
Chris@184 48 #define SAMP_MAX 2147483647
Chris@184 49 #else
Chris@184 50 # define FRACBITS 15
Chris@184 51 # define SAMPPROD int32_t
Chris@184 52 #define SAMP_MAX 32767
Chris@184 53 #endif
Chris@184 54
Chris@184 55 #define SAMP_MIN -SAMP_MAX
Chris@184 56
Chris@184 57 #if defined(CHECK_OVERFLOW)
Chris@184 58 # define CHECK_OVERFLOW_OP(a,op,b) \
Chris@184 59 if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
Chris@184 60 fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); }
Chris@184 61 #endif
Chris@184 62
Chris@184 63
Chris@184 64 # define smul(a,b) ( (SAMPPROD)(a)*(b) )
Chris@184 65 # define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS )
Chris@184 66
Chris@184 67 # define S_MUL(a,b) sround( smul(a,b) )
Chris@184 68
Chris@184 69 # define C_MUL(m,a,b) \
Chris@184 70 do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
Chris@184 71 (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
Chris@184 72
Chris@184 73 # define DIVSCALAR(x,k) \
Chris@184 74 (x) = sround( smul( x, SAMP_MAX/k ) )
Chris@184 75
Chris@184 76 # define C_FIXDIV(c,div) \
Chris@184 77 do { DIVSCALAR( (c).r , div); \
Chris@184 78 DIVSCALAR( (c).i , div); }while (0)
Chris@184 79
Chris@184 80 # define C_MULBYSCALAR( c, s ) \
Chris@184 81 do{ (c).r = sround( smul( (c).r , s ) ) ;\
Chris@184 82 (c).i = sround( smul( (c).i , s ) ) ; }while(0)
Chris@184 83
Chris@184 84 #else /* not FIXED_POINT*/
Chris@184 85
Chris@184 86 # define S_MUL(a,b) ( (a)*(b) )
Chris@184 87 #define C_MUL(m,a,b) \
Chris@184 88 do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
Chris@184 89 (m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
Chris@184 90 # define C_FIXDIV(c,div) /* NOOP */
Chris@184 91 # define C_MULBYSCALAR( c, s ) \
Chris@184 92 do{ (c).r *= (s);\
Chris@184 93 (c).i *= (s); }while(0)
Chris@184 94 #endif
Chris@184 95
Chris@184 96 #ifndef CHECK_OVERFLOW_OP
Chris@184 97 # define CHECK_OVERFLOW_OP(a,op,b) /* noop */
Chris@184 98 #endif
Chris@184 99
Chris@184 100 #define C_ADD( res, a,b)\
Chris@184 101 do { \
Chris@184 102 CHECK_OVERFLOW_OP((a).r,+,(b).r)\
Chris@184 103 CHECK_OVERFLOW_OP((a).i,+,(b).i)\
Chris@184 104 (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
Chris@184 105 }while(0)
Chris@184 106 #define C_SUB( res, a,b)\
Chris@184 107 do { \
Chris@184 108 CHECK_OVERFLOW_OP((a).r,-,(b).r)\
Chris@184 109 CHECK_OVERFLOW_OP((a).i,-,(b).i)\
Chris@184 110 (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
Chris@184 111 }while(0)
Chris@184 112 #define C_ADDTO( res , a)\
Chris@184 113 do { \
Chris@184 114 CHECK_OVERFLOW_OP((res).r,+,(a).r)\
Chris@184 115 CHECK_OVERFLOW_OP((res).i,+,(a).i)\
Chris@184 116 (res).r += (a).r; (res).i += (a).i;\
Chris@184 117 }while(0)
Chris@184 118
Chris@184 119 #define C_SUBFROM( res , a)\
Chris@184 120 do {\
Chris@184 121 CHECK_OVERFLOW_OP((res).r,-,(a).r)\
Chris@184 122 CHECK_OVERFLOW_OP((res).i,-,(a).i)\
Chris@184 123 (res).r -= (a).r; (res).i -= (a).i; \
Chris@184 124 }while(0)
Chris@184 125
Chris@184 126
Chris@184 127 #ifdef FIXED_POINT
Chris@184 128 # define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase))
Chris@184 129 # define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase))
Chris@184 130 # define HALF_OF(x) ((x)>>1)
Chris@184 131 #elif defined(USE_SIMD)
Chris@184 132 # define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
Chris@184 133 # define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
Chris@184 134 # define HALF_OF(x) ((x)*_mm_set1_ps(.5))
Chris@184 135 #else
Chris@184 136 # define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
Chris@184 137 # define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
Chris@184 138 # define HALF_OF(x) ((x)*.5)
Chris@184 139 #endif
Chris@184 140
Chris@184 141 #define kf_cexp(x,phase) \
Chris@184 142 do{ \
Chris@184 143 (x)->r = KISS_FFT_COS(phase);\
Chris@184 144 (x)->i = KISS_FFT_SIN(phase);\
Chris@184 145 }while(0)
Chris@184 146
Chris@184 147
Chris@184 148 /* a debugging function */
Chris@184 149 #define pcpx(c)\
Chris@184 150 fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )
Chris@184 151
Chris@184 152
Chris@184 153 #ifdef KISS_FFT_USE_ALLOCA
Chris@184 154 // define this to allow use of alloca instead of malloc for temporary buffers
Chris@184 155 // Temporary buffers are used in two case:
Chris@184 156 // 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5
Chris@184 157 // 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform.
Chris@184 158 #include <alloca.h>
Chris@184 159 #define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes)
Chris@184 160 #define KISS_FFT_TMP_FREE(ptr)
Chris@184 161 #else
Chris@184 162 #define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes)
Chris@184 163 #define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr)
Chris@184 164 #endif