1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_quaternion_product_single_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 /**
34 @ingroup QuatProd
35 */
36
37 /**
38 @defgroup QuatProdSingle Quaternion Product
39
40 Compute the product of two quaternions.
41 */
42
43 /**
44 @addtogroup QuatProdSingle
45 @{
46 */
47
48 /**
49 @brief Floating-point product of two quaternions.
50 @param[in] qa first quaternion
51 @param[in] qb second quaternion
52 @param[out] qr product of two quaternions
53 */
54
55 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
56
57 #include "arm_helium_utils.h"
arm_quaternion_product_single_f32(const float32_t * qa,const float32_t * qb,float32_t * qr)58 void arm_quaternion_product_single_f32(const float32_t *qa,
59 const float32_t *qb,
60 float32_t *qr)
61 {
62 static uint32_t patternA[4] = { 0, 1, 0, 1 };
63 static uint32_t patternB[4] = { 3, 2, 3, 2 };
64 static uint32_t patternC[4] = { 3, 2, 1, 0 };
65 static float32_t signA[4] = { -1, -1, 1, 1 };
66
67 uint32x4_t vecA = vld1q_u32(patternA);
68 uint32x4_t vecB = vld1q_u32(patternB);
69 uint32x4_t vecC = vld1q_u32(patternC);
70 f32x4_t vecSignA = vld1q_f32(signA);
71
72
73 f32x4_t vecTmpA, vecTmpB, vecAcc;
74
75 vecTmpA = vldrwq_gather_shifted_offset_f32(qa, vecA);
76 vecTmpB = vld1q_f32(qb);
77
78 vecAcc = vcmulq_f32(vecTmpA, vecTmpB);
79 vecAcc = vcmlaq_rot90_f32(vecAcc, vecTmpA, vecTmpB);
80
81 vecTmpA = vldrwq_gather_shifted_offset_f32(qa, vecB);
82 vecTmpB = vldrwq_gather_shifted_offset_f32(qb, vecC);
83
84 vecTmpB = vecTmpB * vecSignA;
85
86 vecAcc = vcmlaq_rot270_f32(vecAcc, vecTmpA, vecTmpB);
87 vecAcc = vcmlaq_f32(vecAcc, vecTmpA, vecTmpB);
88
89 vst1q_f32(qr, vecAcc);
90 }
91
92 #else
arm_quaternion_product_single_f32(const float32_t * qa,const float32_t * qb,float32_t * qr)93 void arm_quaternion_product_single_f32(const float32_t *qa,
94 const float32_t *qb,
95 float32_t *qr)
96 {
97 qr[0] = qa[0] * qb[0] - qa[1] * qb[1] - qa[2] * qb[2] - qa[3] * qb[3];
98 qr[1] = qa[0] * qb[1] + qa[1] * qb[0] + qa[2] * qb[3] - qa[3] * qb[2];
99 qr[2] = qa[0] * qb[2] + qa[2] * qb[0] + qa[3] * qb[1] - qa[1] * qb[3];
100 qr[3] = qa[0] * qb[3] + qa[3] * qb[0] + qa[1] * qb[2] - qa[2] * qb[1];
101 }
102 #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
103
104 /**
105 @} end of QuatProdSingle group
106 */
107