1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_rfft_fast_f64.c
4  * Description:  RFFT & RIFFT Double precision Floating point process function
5  *
6  * $Date:        23 April 2021
7  * $Revision:    V1.9.0
8  *
9  * Target Processor: Cortex-M and Cortex-A cores
10  * -------------------------------------------------------------------- */
11 /*
12  * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
13  *
14  * SPDX-License-Identifier: Apache-2.0
15  *
16  * Licensed under the Apache License, Version 2.0 (the License); you may
17  * not use this file except in compliance with the License.
18  * You may obtain a copy of the License at
19  *
20  * www.apache.org/licenses/LICENSE-2.0
21  *
22  * Unless required by applicable law or agreed to in writing, software
23  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  * See the License for the specific language governing permissions and
26  * limitations under the License.
27  */
28 
29 #include "dsp/transform_functions.h"
30 
stage_rfft_f64(const arm_rfft_fast_instance_f64 * S,float64_t * p,float64_t * pOut)31 void stage_rfft_f64(
32   const arm_rfft_fast_instance_f64 * S,
33         float64_t * p,
34         float64_t * pOut)
35 {
36         uint32_t  k;                                /* Loop Counter */
37         float64_t twR, twI;                         /* RFFT Twiddle coefficients */
38   const float64_t * pCoeff = S->pTwiddleRFFT;       /* Points to RFFT Twiddle factors */
39         float64_t *pA = p;                          /* increasing pointer */
40         float64_t *pB = p;                          /* decreasing pointer */
41         float64_t xAR, xAI, xBR, xBI;               /* temporary variables */
42         float64_t t1a, t1b;                         /* temporary variables */
43         float64_t p0, p1, p2, p3;                   /* temporary variables */
44 
45 
46    k = (S->Sint).fftLen - 1;
47 
48    /* Pack first and last sample of the frequency domain together */
49 
50    xBR = pB[0];
51    xBI = pB[1];
52    xAR = pA[0];
53    xAI = pA[1];
54 
55    twR = *pCoeff++ ;
56    twI = *pCoeff++ ;
57 
58    // U1 = XA(1) + XB(1); % It is real
59    t1a = xBR + xAR  ;
60 
61    // U2 = XB(1) - XA(1); % It is imaginary
62    t1b = xBI + xAI  ;
63 
64    // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI);
65    // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI);
66    *pOut++ = 0.5 * ( t1a + t1b );
67    *pOut++ = 0.5 * ( t1a - t1b );
68 
69    // XA(1) = 1/2*( U1 - imag(U2) +  i*( U1 +imag(U2) ));
70    pB  = p + 2*k;
71    pA += 2;
72 
73    do
74    {
75       /*
76          function X = my_split_rfft(X, ifftFlag)
77          % X is a series of real numbers
78          L  = length(X);
79          XC = X(1:2:end) +i*X(2:2:end);
80          XA = fft(XC);
81          XB = conj(XA([1 end:-1:2]));
82          TW = i*exp(-2*pi*i*[0:L/2-1]/L).';
83          for l = 2:L/2
84             XA(l) = 1/2 * (XA(l) + XB(l) + TW(l) * (XB(l) - XA(l)));
85          end
86          XA(1) = 1/2* (XA(1) + XB(1) + TW(1) * (XB(1) - XA(1))) + i*( 1/2*( XA(1) + XB(1) + i*( XA(1) - XB(1))));
87          X = XA;
88       */
89 
90       xBI = pB[1];
91       xBR = pB[0];
92       xAR = pA[0];
93       xAI = pA[1];
94 
95       twR = *pCoeff++;
96       twI = *pCoeff++;
97 
98       t1a = xBR - xAR ;
99       t1b = xBI + xAI ;
100 
101       // real(tw * (xB - xA)) = twR * (xBR - xAR) - twI * (xBI - xAI);
102       // imag(tw * (xB - xA)) = twI * (xBR - xAR) + twR * (xBI - xAI);
103       p0 = twR * t1a;
104       p1 = twI * t1a;
105       p2 = twR * t1b;
106       p3 = twI * t1b;
107 
108       *pOut++ = 0.5 * (xAR + xBR + p0 + p3 ); //xAR
109       *pOut++ = 0.5 * (xAI - xBI + p1 - p2 ); //xAI
110 
111       pA += 2;
112       pB -= 2;
113       k--;
114    } while (k > 0U);
115 }
116 
117 /* Prepares data for inverse cfft */
merge_rfft_f64(const arm_rfft_fast_instance_f64 * S,float64_t * p,float64_t * pOut)118 void merge_rfft_f64(
119   const arm_rfft_fast_instance_f64 * S,
120         float64_t * p,
121         float64_t * pOut)
122 {
123         uint32_t  k;                                /* Loop Counter */
124         float64_t twR, twI;                         /* RFFT Twiddle coefficients */
125   const float64_t *pCoeff = S->pTwiddleRFFT;        /* Points to RFFT Twiddle factors */
126         float64_t *pA = p;                          /* increasing pointer */
127         float64_t *pB = p;                          /* decreasing pointer */
128         float64_t xAR, xAI, xBR, xBI;               /* temporary variables */
129         float64_t t1a, t1b, r, s, t, u;             /* temporary variables */
130 
131    k = (S->Sint).fftLen - 1;
132 
133    xAR = pA[0];
134    xAI = pA[1];
135 
136    pCoeff += 2 ;
137 
138    *pOut++ = 0.5 * ( xAR + xAI );
139    *pOut++ = 0.5 * ( xAR - xAI );
140 
141    pB  =  p + 2*k ;
142    pA +=  2	   ;
143 
144    while (k > 0U)
145    {
146       /* G is half of the frequency complex spectrum */
147       //for k = 2:N
148       //    Xk(k) = 1/2 * (G(k) + conj(G(N-k+2)) + Tw(k)*( G(k) - conj(G(N-k+2))));
149       xBI =   pB[1]    ;
150       xBR =   pB[0]    ;
151       xAR =  pA[0];
152       xAI =  pA[1];
153 
154       twR = *pCoeff++;
155       twI = *pCoeff++;
156 
157       t1a = xAR - xBR ;
158       t1b = xAI + xBI ;
159 
160       r = twR * t1a;
161       s = twI * t1b;
162       t = twI * t1a;
163       u = twR * t1b;
164 
165       // real(tw * (xA - xB)) = twR * (xAR - xBR) - twI * (xAI - xBI);
166       // imag(tw * (xA - xB)) = twI * (xAR - xBR) + twR * (xAI - xBI);
167       *pOut++ = 0.5 * (xAR + xBR - r - s ); //xAR
168       *pOut++ = 0.5 * (xAI - xBI + t - u ); //xAI
169 
170       pA += 2;
171       pB -= 2;
172       k--;
173    }
174 
175 }
176 
177 /**
178   @ingroup groupTransforms
179 */
180 
181 
182 /**
183   @addtogroup RealFFT
184   @{
185 */
186 
187 /**
188   @brief         Processing function for the Double Precision floating-point real FFT.
189   @param[in]     S         points to an arm_rfft_fast_instance_f64 structure
190   @param[in]     p         points to input buffer (Source buffer is modified by this function.)
191   @param[in]     pOut      points to output buffer
192   @param[in]     ifftFlag
193                    - value = 0: RFFT
194                    - value = 1: RIFFT
195   @return        none
196 */
197 
arm_rfft_fast_f64(arm_rfft_fast_instance_f64 * S,float64_t * p,float64_t * pOut,uint8_t ifftFlag)198 void arm_rfft_fast_f64(
199   arm_rfft_fast_instance_f64 * S,
200   float64_t * p,
201   float64_t * pOut,
202   uint8_t ifftFlag)
203 {
204    arm_cfft_instance_f64 * Sint = &(S->Sint);
205    Sint->fftLen = S->fftLenRFFT / 2;
206 
207    /* Calculation of Real FFT */
208    if (ifftFlag)
209    {
210       /*  Real FFT compression */
211       merge_rfft_f64(S, p, pOut);
212 
213       /* Complex radix-4 IFFT process */
214       arm_cfft_f64( Sint, pOut, ifftFlag, 1);
215    }
216    else
217    {
218       /* Calculation of RFFT of input */
219       arm_cfft_f64( Sint, p, ifftFlag, 1);
220 
221       /*  Real FFT extraction */
222       stage_rfft_f64(S, p, pOut);
223    }
224 }
225 
226 /**
227 * @} end of RealFFT group
228 */
229