1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_quaternion_product_f32.c
4  * Description:  Floating-point quaternion product
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/quaternion_math_functions.h"
30 #include <math.h>
31 
32 /**
33   @ingroup groupQuaternionMath
34  */
35 
36 /**
37   @defgroup QuatProd Quaternion Product
38 
39   Compute the product of quaternions.
40  */
41 
42 /**
43   @ingroup QuatProd
44  */
45 
46 /**
47   @defgroup QuatProdVect Elementwise Quaternion Product
48 
49   Compute the elementwise product of quaternions.
50  */
51 
52 /**
53   @addtogroup QuatProdVect
54   @{
55  */
56 
57 /**
58   @brief         Floating-point elementwise product two quaternions.
59   @param[in]     qa                  first array of quaternions
60   @param[in]     qb                  second array of quaternions
61   @param[out]    qr                   elementwise product of quaternions
62   @param[in]     nbQuaternions       number of quaternions in the array
63  */
64 
65 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
66 
67 #include "arm_helium_utils.h"
68 
arm_quaternion_product_f32(const float32_t * qa,const float32_t * qb,float32_t * qr,uint32_t nbQuaternions)69 ARM_DSP_ATTRIBUTE void arm_quaternion_product_f32(const float32_t *qa,
70     const float32_t *qb,
71     float32_t *qr,
72     uint32_t nbQuaternions)
73 {
74     static uint32_t patternA[4] = { 0, 1, 0, 1 };
75     static uint32_t patternB[4] = { 3, 2, 3, 2 };
76     static uint32_t patternC[4] = { 3, 2, 1, 0 };
77     static float32_t   signA[4] = { -1, -1, 1, 1 };
78 
79     uint32x4_t vecA = vld1q_u32(patternA);
80     uint32x4_t vecB = vld1q_u32(patternB);
81     uint32x4_t vecC = vld1q_u32(patternC);
82     f32x4_t vecSignA = vld1q_f32(signA);
83 
84     while (nbQuaternions > 0U)
85     {
86         f32x4_t vecTmpA, vecTmpB, vecAcc;
87 
88         vecTmpA = vldrwq_gather_shifted_offset_f32(qa, vecA);
89         vecTmpB = vld1q(qb);
90         /*
91          * vcmul(r, [a1, a2, a1, a2], [b1, b2, b3, b4], 0)
92          */
93         vecAcc = vcmulq(vecTmpA, vecTmpB);
94         /*
95          * vcmla(r, [a1, a2, a1, a2], [b1, b2, b3, b4], 90)
96          */
97         vecAcc = vcmlaq_rot90(vecAcc, vecTmpA, vecTmpB);
98 
99         vecTmpA = vldrwq_gather_shifted_offset_f32(qa, vecB);
100         vecTmpB = vldrwq_gather_shifted_offset_f32(qb, vecC);
101         /*
102          * build [-b4, -b3, b2, b1]
103          */
104         vecTmpB = vecTmpB * vecSignA;
105         /*
106          * vcmla(r, [a4, a3, a4, a3], [-b4, -b3, b2, b1], 270)
107          */
108         vecAcc = vcmlaq_rot270(vecAcc, vecTmpA, vecTmpB);
109         /*
110          * vcmla(r, [a4, a3, a4, a3], [-b4, -b3, b2, b1], 0)
111          */
112         vecAcc = vcmlaq(vecAcc, vecTmpA, vecTmpB);
113         /*
114          * store accumulator
115          */
116         vst1q_f32(qr, vecAcc);
117 
118         /* move to next quaternion */
119         qa += 4;
120         qb += 4;
121         qr += 4;
122 
123         nbQuaternions--;
124     }
125 }
126 
127 #else
128 
arm_quaternion_product_f32(const float32_t * qa,const float32_t * qb,float32_t * qr,uint32_t nbQuaternions)129 ARM_DSP_ATTRIBUTE void arm_quaternion_product_f32(const float32_t *qa,
130     const float32_t *qb,
131     float32_t *qr,
132     uint32_t nbQuaternions)
133 {
134    uint32_t i;
135    for(i=0; i < nbQuaternions; i++)
136    {
137      arm_quaternion_product_single_f32(qa, qb, qr);
138 
139      qa += 4;
140      qb += 4;
141      qr += 4;
142    }
143 }
144 #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
145 
146 /**
147   @} end of QuatProdVect group
148  */
149