1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_cmplx_conj_f32.c
4  * Description:  Floating-point complex conjugate
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/complex_math_functions.h"
30 
31 /**
32   @ingroup groupCmplxMath
33  */
34 
35 /**
36   @defgroup cmplx_conj Complex Conjugate
37 
38   Conjugates the elements of a complex data vector.
39 
40   The <code>pSrc</code> points to the source data and
41   <code>pDst</code> points to the destination data where the result should be written.
42   <code>numSamples</code> specifies the number of complex samples
43   and the data in each array is stored in an interleaved fashion
44   (real, imag, real, imag, ...).
45   Each array has a total of <code>2*numSamples</code> values.
46 
47   The underlying algorithm is used:
48   <pre>
49   for (n = 0; n < numSamples; n++) {
50       pDst[(2*n)  ] =  pSrc[(2*n)  ];    // real part
51       pDst[(2*n)+1] = -pSrc[(2*n)+1];    // imag part
52   }
53   </pre>
54 
55   There are separate functions for floating-point, Q15, and Q31 data types.
56  */
57 
58 /**
59   @addtogroup cmplx_conj
60   @{
61  */
62 
63 /**
64   @brief         Floating-point complex conjugate.
65   @param[in]     pSrc        points to the input vector
66   @param[out]    pDst        points to the output vector
67   @param[in]     numSamples  number of samples in each vector
68  */
69 
70 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
71 
arm_cmplx_conj_f32(const float32_t * pSrc,float32_t * pDst,uint32_t numSamples)72 void arm_cmplx_conj_f32(
73     const float32_t * pSrc,
74     float32_t * pDst,
75     uint32_t numSamples)
76 {
77     static const float32_t cmplx_conj_sign[4] = { 1.0f, -1.0f, 1.0f, -1.0f };
78     uint32_t blockSize = numSamples * CMPLX_DIM;   /* loop counters */
79     uint32_t blkCnt;
80     f32x4_t vecSrc;
81     f32x4_t vecSign;
82 
83     /*
84      * load sign vector
85      */
86     vecSign = *(f32x4_t *) cmplx_conj_sign;
87 
88     /* Compute 4 real samples at a time */
89     blkCnt = blockSize >> 2U;
90 
91     while (blkCnt > 0U)
92     {
93         vecSrc = vld1q(pSrc);
94         vst1q(pDst,vmulq(vecSrc, vecSign));
95         /*
96          * Decrement the blkCnt loop counter
97          * Advance vector source and destination pointers
98          */
99         pSrc += 4;
100         pDst += 4;
101         blkCnt--;
102     }
103 
104      /* Tail */
105     blkCnt = (blockSize & 0x3) >> 1;
106 
107     while (blkCnt > 0U)
108     {
109       /* C[0] + jC[1] = A[0]+ j(-1)A[1] */
110 
111       /* Calculate Complex Conjugate and store result in destination buffer. */
112       *pDst++ =  *pSrc++;
113       *pDst++ = -*pSrc++;
114 
115       /* Decrement loop counter */
116       blkCnt--;
117     }
118 
119 }
120 
121 #else
arm_cmplx_conj_f32(const float32_t * pSrc,float32_t * pDst,uint32_t numSamples)122 void arm_cmplx_conj_f32(
123   const float32_t * pSrc,
124         float32_t * pDst,
125         uint32_t numSamples)
126 {
127         uint32_t blkCnt;                               /* Loop counter */
128 
129 #if defined(ARM_MATH_NEON) && !defined(ARM_MATH_AUTOVECTORIZE)
130    float32x4_t zero;
131    float32x4x2_t vec;
132 
133    zero = vdupq_n_f32(0.0f);
134 
135    /* Compute 4 outputs at a time */
136    blkCnt = numSamples >> 2U;
137 
138    while (blkCnt > 0U)
139    {
140      /* C[0]+jC[1] = A[0]+(-1)*jA[1] */
141      /* Calculate Complex Conjugate and then store the results in the destination buffer. */
142      vec = vld2q_f32(pSrc);
143      vec.val[1] = vsubq_f32(zero,vec.val[1]);
144      vst2q_f32(pDst,vec);
145 
146      /* Increment pointers */
147      pSrc += 8;
148      pDst += 8;
149 
150      /* Decrement the loop counter */
151      blkCnt--;
152    }
153 
154    /* Tail */
155    blkCnt = numSamples & 0x3;
156 
157 #else
158 #if defined (ARM_MATH_LOOPUNROLL) && !defined(ARM_MATH_AUTOVECTORIZE)
159 
160   /* Loop unrolling: Compute 4 outputs at a time */
161   blkCnt = numSamples >> 2U;
162 
163   while (blkCnt > 0U)
164   {
165     /* C[0] + jC[1] = A[0]+ j(-1)A[1] */
166 
167     /* Calculate Complex Conjugate and store result in destination buffer. */
168     *pDst++ =  *pSrc++;
169     *pDst++ = -*pSrc++;
170 
171     *pDst++ =  *pSrc++;
172     *pDst++ = -*pSrc++;
173 
174     *pDst++ =  *pSrc++;
175     *pDst++ = -*pSrc++;
176 
177     *pDst++ =  *pSrc++;
178     *pDst++ = -*pSrc++;
179 
180     /* Decrement loop counter */
181     blkCnt--;
182   }
183 
184   /* Loop unrolling: Compute remaining outputs */
185   blkCnt = numSamples % 0x4U;
186 
187 #else
188 
189   /* Initialize blkCnt with number of samples */
190   blkCnt = numSamples;
191 
192 #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
193 #endif /* #if defined (ARM_MATH_NEON) */
194 
195   while (blkCnt > 0U)
196   {
197     /* C[0] + jC[1] = A[0]+ j(-1)A[1] */
198 
199     /* Calculate Complex Conjugate and store result in destination buffer. */
200     *pDst++ =  *pSrc++;
201     *pDst++ = -*pSrc++;
202 
203     /* Decrement loop counter */
204     blkCnt--;
205   }
206 
207 }
208 #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
209 
210 /**
211   @} end of cmplx_conj group
212  */
213