@@ -9,17 +9,17 @@ namespace dsplib {
99
1010// -------------------------------------------------------------------------------------------------------------
1111// FFT implementation for small sizes
12- class SmallFftPow2C : public BaseFftPlanC
12+ class SmallFftC : public BaseFftPlanC
1313{
1414public:
15- friend class SmallFftPow2R ;
15+ friend class SmallFftR ;
1616
17- explicit SmallFftPow2C (int n)
17+ explicit SmallFftC (int n)
1818 : n_{n} {
19- DSPLIB_ASSERT ((n >= 1 ) && (n <= 8 ) , " only small power-of-two sizes are supported: 1, 2, 4, 8" );
19+ DSPLIB_ASSERT (is_supported (n) , " only small sizes are supported: 1, 2, 3 , 4, 8" );
2020 }
2121
22- ~SmallFftPow2C () override {
22+ ~SmallFftC () override {
2323 }
2424
2525 void solve (const cmplx_t * x, cmplx_t * y, int n) const final {
@@ -31,6 +31,9 @@ class SmallFftPow2C : public BaseFftPlanC
3131 case 2 :
3232 _fft_n2 (x, y);
3333 break ;
34+ case 3 :
35+ _fft_n3 (x, y);
36+ break ;
3437 case 4 :
3538 _fft_n4 (x, y);
3639 break ;
@@ -53,6 +56,10 @@ class SmallFftPow2C : public BaseFftPlanC
5356 return n_;
5457 }
5558
59+ static bool is_supported (int n) noexcept {
60+ return (n == 1 || n == 2 || n == 3 || n == 4 || n == 8 );
61+ }
62+
5663private:
5764 static void _fft_n2 (const cmplx_t * restrict x, cmplx_t * restrict y) noexcept {
5865 y[0 ].re = x[0 ].re + x[1 ].re ;
@@ -61,6 +68,28 @@ class SmallFftPow2C : public BaseFftPlanC
6168 y[1 ].im = x[0 ].im - x[1 ].im ;
6269 }
6370
71+ static void _fft_n3 (const cmplx_t * restrict x, cmplx_t * restrict y) noexcept {
72+ constexpr real_t c = -0.5 ;
73+ constexpr real_t d = 0.866025403784439 ;
74+
75+ y[0 ].re = x[0 ].re + x[1 ].re + x[2 ].re ;
76+ y[0 ].im = x[0 ].im + x[1 ].im + x[2 ].im ;
77+
78+ const real_t re1_c = x[1 ].re * c;
79+ const real_t im1_d = x[1 ].im * d;
80+ const real_t re2_c = x[2 ].re * c;
81+ const real_t im2_d = x[2 ].im * d;
82+ y[1 ].re = x[0 ].re + (re1_c + im1_d) + (re2_c - im2_d);
83+ y[2 ].re = x[0 ].re + (re1_c - im1_d) + (re2_c + im2_d);
84+
85+ const real_t re1_d = x[1 ].re * d;
86+ const real_t im1_c = x[1 ].im * c;
87+ const real_t re2_d = x[2 ].re * d;
88+ const real_t im2_c = x[2 ].im * c;
89+ y[1 ].im = x[0 ].im + (-re1_d + im1_c) + (re2_d + im2_c);
90+ y[2 ].im = x[0 ].im + (re1_d + im1_c) + (-re2_d + im2_c);
91+ }
92+
6493 static void _fft_n4 (const cmplx_t * restrict x, cmplx_t * restrict y) noexcept {
6594 y[0 ].re = x[0 ].re + x[1 ].re + x[2 ].re + x[3 ].re ;
6695 y[0 ].im = x[0 ].im + x[1 ].im + x[2 ].im + x[3 ].im ;
@@ -101,15 +130,15 @@ class SmallFftPow2C : public BaseFftPlanC
101130};
102131
103132// -------------------------------------------------------------------------------------------------------------
104- class SmallFftPow2R : public BaseFftPlanR
133+ class SmallFftR : public BaseFftPlanR
105134{
106135public:
107- explicit SmallFftPow2R (int n)
136+ explicit SmallFftR (int n)
108137 : n_{n} {
109- DSPLIB_ASSERT ((n >= 1 ) && (n <= 8 ) , " only small power-of-two sizes are supported: 1, 2, 4, 8" );
138+ DSPLIB_ASSERT (is_supported (n) , " only small sizes are supported: 1, 2, 3 , 4, 8" );
110139 }
111140
112- ~SmallFftPow2R () override {
141+ ~SmallFftR () override {
113142 }
114143
115144 void solve (const real_t * x, cmplx_t * y, int n) const final {
@@ -121,6 +150,9 @@ class SmallFftPow2R : public BaseFftPlanR
121150 case 2 :
122151 _fft_n2 (x, y);
123152 break ;
153+ case 3 :
154+ _fft_n3 (x, y);
155+ break ;
124156 case 4 :
125157 _fft_n4 (x, y);
126158 break ;
@@ -143,6 +175,10 @@ class SmallFftPow2R : public BaseFftPlanR
143175 return n_;
144176 }
145177
178+ static bool is_supported (int n) noexcept {
179+ return (n == 1 || n == 2 || n == 3 || n == 4 || n == 8 );
180+ }
181+
146182private:
147183 static void _fft_n2 (const real_t * restrict x, cmplx_t * restrict y) noexcept {
148184 y[0 ].re = x[0 ] + x[1 ];
@@ -151,6 +187,24 @@ class SmallFftPow2R : public BaseFftPlanR
151187 y[1 ].im = 0 ;
152188 }
153189
190+ static void _fft_n3 (const real_t * restrict x, cmplx_t * restrict y) noexcept {
191+ constexpr real_t c = -0.5 ;
192+ constexpr real_t d = 0.866025403784439 ;
193+
194+ y[0 ].re = x[0 ] + x[1 ] + x[2 ];
195+ y[0 ].im = 0 ;
196+
197+ const real_t re1_c = x[1 ] * c;
198+ const real_t re2_c = x[2 ] * c;
199+ y[1 ].re = x[0 ] + re1_c + re2_c;
200+ y[2 ].re = y[1 ].re ;
201+
202+ const real_t re1_d = x[1 ] * d;
203+ const real_t re2_d = x[2 ] * d;
204+ y[1 ].im = (-re1_d) + (re2_d);
205+ y[2 ].im = -y[1 ].im ;
206+ }
207+
154208 static void _fft_n4 (const real_t * restrict x, cmplx_t * restrict y) noexcept {
155209 y[0 ].re = x[0 ] + x[1 ] + x[2 ] + x[3 ];
156210 y[0 ].im = 0 ;
@@ -169,7 +223,7 @@ class SmallFftPow2R : public BaseFftPlanR
169223 p1[1 ] = x[1 ] + x[5 ];
170224 p1[2 ] = x[2 ] + x[6 ];
171225 p1[3 ] = x[3 ] + x[7 ];
172- SmallFftPow2R ::_fft_n4 (p1, r1);
226+ SmallFftR ::_fft_n4 (p1, r1);
173227
174228 cmplx_t p2[4 ];
175229 cmplx_t r2[4 ];
@@ -178,7 +232,7 @@ class SmallFftPow2R : public BaseFftPlanR
178232 p2[2 ].re = 0 ;
179233 p2[2 ].im = x[6 ] - x[2 ];
180234 p2[3 ] = (x[3 ] - x[7 ]) * cmplx_t {-0.707106781186548 , -0.707106781186548 };
181- SmallFftPow2C ::_fft_n4 (p2, r2);
235+ SmallFftC ::_fft_n4 (p2, r2);
182236
183237 for (int i = 0 ; i < 4 ; ++i) {
184238 *y++ = r1[i];
0 commit comments