1 /*
2     SPDX-FileCopyrightText: 2003-2010 Mark Borgerding <Mark@Borgerding.net>
3     SPDX-License-Identifier: BSD-3-Clause
4 */
5 
6 #ifndef _KISS_FFT_GUTS_H
7 #define _KISS_FFT_GUTS_H
8 
9 /* kiss_fft.h
10    defines kiss_fft_scalar as either short or a float type
11    and defines
12    typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
13 #include "kiss_fft.h"
14 #include <limits.h>
15 
16 #define MAXFACTORS 32
17 /* e.g. an fft of length 128 has 4 factors
18  as far as kissfft is concerned
19  4*4*4*2
20  */
21 
22 struct kiss_fft_state
23 {
24     int nfft;
25     int inverse;
26     int factors[2 * MAXFACTORS];
27     kiss_fft_cpx twiddles[1];
28 };
29 
30 /*
31   Explanation of macros dealing with complex math:
32 
33    C_MUL(m,a,b)         : m = a*b
34    C_FIXDIV( c , div )  : if a fixed point impl., c /= div. noop otherwise
35    C_SUB( res, a,b)     : res = a - b
36    C_SUBFROM( res , a)  : res -= a
37    C_ADDTO( res , a)    : res += a
38  * */
39 #ifdef FIXED_POINT
40 #if (FIXED_POINT == 32)
41 #define FRACBITS 31
42 #define SAMPPROD int64_t
43 #define SAMP_MAX 2147483647
44 #else
45 #define FRACBITS 15
46 #define SAMPPROD int32_t
47 #define SAMP_MAX 32767
48 #endif
49 
50 #define SAMP_MIN -SAMP_MAX
51 
52 #if defined(CHECK_OVERFLOW)
53 #define CHECK_OVERFLOW_OP(a, op, b)                                                                                                                            \
54     if ((SAMPPROD)(a)op(SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a)op(SAMPPROD)(b) < SAMP_MIN) {                                                                  \
55         fprintf(stderr, "WARNING:overflow @ " __FILE__ "(%d): (%d " #op " %d) = %ld\n", __LINE__, (a), (b), (SAMPPROD)(a)op(SAMPPROD)(b));                     \
56     }
57 #endif
58 
59 #define smul(a, b) ((SAMPPROD)(a) * (b))
60 #define sround(x) (kiss_fft_scalar)(((x) + (1 << (FRACBITS - 1))) >> FRACBITS)
61 
62 #define S_MUL(a, b) sround(smul(a, b))
63 
64 #define C_MUL(m, a, b)                                                                                                                                         \
65     do {                                                                                                                                                       \
66         (m).r = sround(smul((a).r, (b).r) - smul((a).i, (b).i));                                                                                               \
67         (m).i = sround(smul((a).r, (b).i) + smul((a).i, (b).r));                                                                                               \
68     } while (0)
69 
70 #define DIVSCALAR(x, k) (x) = sround(smul(x, SAMP_MAX / k))
71 
72 #define C_FIXDIV(c, div)                                                                                                                                       \
73     do {                                                                                                                                                       \
74         DIVSCALAR((c).r, div);                                                                                                                                 \
75         DIVSCALAR((c).i, div);                                                                                                                                 \
76     } while (0)
77 
78 #define C_MULBYSCALAR(c, s)                                                                                                                                    \
79     do {                                                                                                                                                       \
80         (c).r = sround(smul((c).r, s));                                                                                                                        \
81         (c).i = sround(smul((c).i, s));                                                                                                                        \
82     } while (0)
83 
84 #else /* not FIXED_POINT*/
85 
86 #define S_MUL(a, b) ((a) * (b))
87 #define C_MUL(m, a, b)                                                                                                                                         \
88     do {                                                                                                                                                       \
89         (m).r = (a).r * (b).r - (a).i * (b).i;                                                                                                                 \
90         (m).i = (a).r * (b).i + (a).i * (b).r;                                                                                                                 \
91     } while (0)
92 #define C_FIXDIV(c, div) /* NOOP */
93 #define C_MULBYSCALAR(c, s)                                                                                                                                    \
94     do {                                                                                                                                                       \
95         (c).r *= (s);                                                                                                                                          \
96         (c).i *= (s);                                                                                                                                          \
97     } while (0)
98 #endif
99 
100 #ifndef CHECK_OVERFLOW_OP
101 #define CHECK_OVERFLOW_OP(a, op, b) /* noop */
102 #endif
103 
104 #define C_ADD(res, a, b)                                                                                                                                       \
105     do {                                                                                                                                                       \
106         CHECK_OVERFLOW_OP((a).r, +, (b).r)                                                                                                                     \
107         CHECK_OVERFLOW_OP((a).i, +, (b).i)                                                                                                                     \
108         (res).r = (a).r + (b).r;                                                                                                                               \
109         (res).i = (a).i + (b).i;                                                                                                                               \
110     } while (0)
111 #define C_SUB(res, a, b)                                                                                                                                       \
112     do {                                                                                                                                                       \
113         CHECK_OVERFLOW_OP((a).r, -, (b).r)                                                                                                                     \
114         CHECK_OVERFLOW_OP((a).i, -, (b).i)                                                                                                                     \
115         (res).r = (a).r - (b).r;                                                                                                                               \
116         (res).i = (a).i - (b).i;                                                                                                                               \
117     } while (0)
118 #define C_ADDTO(res, a)                                                                                                                                        \
119     do {                                                                                                                                                       \
120         CHECK_OVERFLOW_OP((res).r, +, (a).r)                                                                                                                   \
121         CHECK_OVERFLOW_OP((res).i, +, (a).i)                                                                                                                   \
122         (res).r += (a).r;                                                                                                                                      \
123         (res).i += (a).i;                                                                                                                                      \
124     } while (0)
125 
126 #define C_SUBFROM(res, a)                                                                                                                                      \
127     do {                                                                                                                                                       \
128         CHECK_OVERFLOW_OP((res).r, -, (a).r)                                                                                                                   \
129         CHECK_OVERFLOW_OP((res).i, -, (a).i)                                                                                                                   \
130         (res).r -= (a).r;                                                                                                                                      \
131         (res).i -= (a).i;                                                                                                                                      \
132     } while (0)
133 
134 #ifdef FIXED_POINT
135 #define KISS_FFT_COS(phase) floor(.5 + SAMP_MAX * cos(phase))
136 #define KISS_FFT_SIN(phase) floor(.5 + SAMP_MAX * sin(phase))
137 #define HALF_OF(x) ((x) >> 1)
138 #elif defined(USE_SIMD)
139 #define KISS_FFT_COS(phase) _mm_set1_ps(cos(phase))
140 #define KISS_FFT_SIN(phase) _mm_set1_ps(sin(phase))
141 #define HALF_OF(x) ((x)*_mm_set1_ps(.5))
142 #else
143 #define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
144 #define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
145 #define HALF_OF(x) ((x)*.5)
146 #endif
147 
148 #define kf_cexp(x, phase)                                                                                                                                      \
149     do {                                                                                                                                                       \
150         (x)->r = KISS_FFT_COS(phase);                                                                                                                          \
151         (x)->i = KISS_FFT_SIN(phase);                                                                                                                          \
152     } while (0)
153 
154 /* a debugging function */
155 #define pcpx(c) fprintf(stderr, "%g + %gi\n", (double)((c)->r), (double)((c)->i))
156 
157 #ifdef KISS_FFT_USE_ALLOCA
158 // define this to allow use of alloca instead of malloc for temporary buffers
159 // Temporary buffers are used in two case:
160 // 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5
161 // 2. "in-place" FFTs.  Notice the quotes, since kissfft does not really do an in-place transform.
162 #include <alloca.h>
163 #define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes)
164 #define KISS_FFT_TMP_FREE(ptr)
165 #else
166 #define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes)
167 #define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr)
168 #endif
169 
170 #endif
171