AFBR-S50 API Reference Manual v1.5.6
AFBR-S50 Time-of-Flight Sensor SDK for Embedded Software
Loading...
Searching...
No Matches
fp_mul.h
Go to the documentation of this file.
1/*************************************************************************/
37#ifndef FP_MUL_H
38#define FP_MUL_H
39#ifdef __cplusplus
40extern "C" {
41#endif
42
43/*!***************************************************************************
44 * @addtogroup argus_fp
45 * @{
46 *****************************************************************************/
47
48#include "fp_def.h"
49#include "utility/fp_rnd.h"
50
51/*!***************************************************************************
52 * Set to use hardware division (Cortex-M3/4) over software division (Cortex-M0/1).
53 *****************************************************************************/
54#ifndef USE_64BIT_MUL
55#define USE_64BIT_MUL 0
56#endif
57
58#if !USE_64BIT_MUL
59/*!***************************************************************************
60 * @brief Long multiplication of two unsigned 32-bit into an 64-bit value on
61 * 32-bit architecture.
62 *
63 * @details w (two words) gets the product of u and v (one word each).
64 * w[0] is the most significant word of the result, w[1] the least.
65 * (The words are in big-endian order).
66 * It is Knuth's Algorithm M from [Knu2] section 4.3.1.
67 * *
68 * @see http://www.hackersdelight.org/hdcodetxt/muldwu.c.txt
69 *
70 * @param w The result (u * v) value given as two unsigned 32-bit numbers:
71 * w[0] is the most significant word of the result, w[1] the least.
72 * (The words are in big-endian order).
73 * @param u Left hand side of the multiplication.
74 * @param v Right hand side of the multiplication.
75 *****************************************************************************/
76inline void muldwu(uint32_t w[], uint32_t u, uint32_t v)
77{
78 const uint32_t u0 = u >> 16U;
79 const uint32_t u1 = u & 0xFFFFU;
80 const uint32_t v0 = v >> 16U;
81 const uint32_t v1 = v & 0xFFFFU;
82
83 uint32_t t = u1 * v1;
84 const uint32_t w3 = t & 0xFFFFU;
85 uint32_t k = t >> 16U;
86
87 t = u0 * v1 + k;
88 const uint32_t w2 = t & 0xFFFFU;
89 const uint32_t w1 = t >> 16U;
90
91 t = u1 * v0 + w2;
92 k = t >> 16U;
93
94 w[0] = u0 * v0 + w1 + k;
95 w[1] = (t << 16U) + w3;
96}
97#endif
98
99/*!***************************************************************************
100 * @brief 64-bit implementation of an unsigned multiplication with fixed point format.
101 *
102 * @details Algorithm to evaluate a*b, where a and b are arbitrary fixed point
103 * number of 32-bit width. The multiplication is done in 64-bit and
104 * the result is shifted down by the passed shift parameter in order
105 * to return a 32-bit value.
106 * The shift is executed with correct rounding.
107 *
108 * Note that the result must fit into the 32-bit value. An assertion
109 * error occurs otherwise (or undefined behavior of no assert available).
110 *
111 * @param u The left parameter in UQx1.y1 format
112 * @param v The right parameter in UQx2.y2 format
113 * @param shift The final right shift (rounding) value.
114 * @return Result = (a*b)>>shift in UQx.(y1+y2-shift) format.
115 *****************************************************************************/
116inline uint32_t fp_mulu(uint32_t u, uint32_t v, uint_fast8_t shift)
117{
118 assert(shift <= 32);
119#if USE_64BIT_MUL
120 const uint64_t w = (uint64_t)u * (uint64_t)v;
121 return (uint32_t)((w >> shift) + ((w >> (shift-1)) & 1U));
122#else
123 uint32_t tmp[2] = { 0 };
124 muldwu(tmp, u, v);
125
126 assert(shift ? tmp[0] <= (UINT32_MAX >> (32-shift)) : tmp[0] == 0);
127
128 if (32 - shift)
129 return ((tmp[0] << (32 - shift)) + fp_rndu(tmp[1], shift));
130 else
131 return tmp[1] > (UINT32_MAX >> 1) ? tmp[0] + 1 : tmp[0];
132#endif
133}
134
135/*!***************************************************************************
136 * @brief 64-bit implementation of a signed multiplication with fixed point format.
137 *
138 * @details Algorithm to evaluate a*b, where a and b are arbitrary fixed point
139 * number of 32-bit width. The multiplication is done in 64-bit and
140 * the result is shifted down by the passed shift parameter in order
141 * to return a 32-bit value.
142 * The shift is executed with correct rounding.
143 *
144 * Note that the result must fit into the 32-bit value. An assertion
145 * error occurs otherwise (or undefined behavior of no assert available).
146 *
147 * @param u The left parameter in Qx1.y1 format
148 * @param v The right parameter in Qx2.y2 format
149 * @param shift The final right shift (rounding) value.
150 * @return Result = (a*b)>>shift in Qx.(y1+y2-shift) format.
151 *****************************************************************************/
152inline int32_t fp_muls(int32_t u, int32_t v, uint_fast8_t shift)
153{
154 int_fast8_t sign = 1;
155
156 uint32_t u2, v2;
157 if(u < 0) { u2 = (uint32_t)-u; sign = -sign; } else { u2 = (uint32_t)u; }
158 if(v < 0) { v2 = (uint32_t)-v; sign = -sign; } else { v2 = (uint32_t)v; }
159
160 const uint32_t res = fp_mulu(u2, v2, shift);
161
162 assert(sign > 0 ? res <= 0x7FFFFFFFU : res <= 0x80000000U);
163
164 return sign > 0 ? (int32_t)res : -(int32_t)res;
165}
166
167
168/*!***************************************************************************
169 * @brief 48-bit implementation of a unsigned multiplication with fixed point format.
170 *
171 * @details Algorithm to evaluate a*b, where a and b are arbitrary fixed point
172 * numbers with 32-bit unsigned and 16-bit unsigned format respectively.
173 * The multiplication is done in two 16x16-bit operations and the
174 * result is shifted down by the passed shift parameter in order to
175 * return a 32-bit value.
176 *
177 * Note that the result must fit into the 32-bit value. An assertion
178 * error occurs otherwise (or undefined behavior of no assert available).
179 *
180 * @param u The left parameter in Qx1.y1 format
181 * @param v The right parameter in Qx2.y2 format
182 * @param shift The final right shift (rounding) value.
183 * @return Result = (a*b)>>shift in Qx.(y1+y2-shift) format.
184 *****************************************************************************/
185inline uint32_t fp_mul_u32_u16(uint32_t u, uint16_t v, uint_fast8_t shift)
186{
187 assert(shift <= 48);
188
189 if (shift > 16)
190 {
191 uint32_t msk = 0xFFFFU;
192 uint32_t a = (u >> 16U) * v;
193 uint32_t b = (msk & u) * v;
194 return fp_rndu(a, shift - 16) + fp_rndu(b, shift);
195 }
196 else
197 {
198 uint32_t msk = ~(0xFFFFFFFFU << shift);
199 uint32_t a = (u >> shift) * v;
200 uint32_t b = fp_rndu((msk & u) * v, shift);
201 return a + b;
202 }
203}
204
205/*!***************************************************************************
206 * @brief 48-bit implementation of an unsigned/signed multiplication with fixed point format.
207 *
208 * @details Algorithm to evaluate a*b, where a and b are arbitrary fixed point
209 * numbers with 32-bit signed and 16-bit unsigned format respectively.
210 * The multiplication is done in two 16x16-bit operations and the
211 * result is shifted down by the passed shift parameter in order to
212 * return a 32-bit value.
213 * The shift is executed with correct rounding.
214 *
215 * Note that the result must fit into the 32-bit value. An assertion
216 * error occurs otherwise (or undefined behavior of no assert available).
217 *
218 * @param u The left parameter in Qx1.y1 format
219 * @param v The right parameter in Qx2.y2 format
220 * @param shift The final right shift (rounding) value.
221 * @return Result = (a*b)>>shift in Qx.(y1+y2-shift) format.
222 *****************************************************************************/
223inline int32_t fp_mul_s32_u16(int32_t u, uint16_t v, uint_fast8_t shift)
224{
225 return u >= 0 ?
226 (int32_t)fp_mul_u32_u16((uint32_t)u, v, shift) :
227 -(int32_t)fp_mul_u32_u16((uint32_t)-u, v, shift);
228}
229
231#ifdef __cplusplus
232} // extern "C"
233#endif
234#endif /* FP_MUL_H */
This file is part of the AFBR-S50 API.
This file is part of the AFBR-S50 API.
uint32_t fp_rndu(uint32_t Q, uint_fast8_t n)
Converting with rounding from UQx.n1 to UQx.n2.
Definition fp_rnd.h:60
int32_t fp_mul_s32_u16(int32_t u, uint16_t v, uint_fast8_t shift)
48-bit implementation of an unsigned/signed multiplication with fixed point format.
Definition fp_mul.h:223
int32_t fp_muls(int32_t u, int32_t v, uint_fast8_t shift)
64-bit implementation of a signed multiplication with fixed point format.
Definition fp_mul.h:152
uint32_t fp_mul_u32_u16(uint32_t u, uint16_t v, uint_fast8_t shift)
48-bit implementation of a unsigned multiplication with fixed point format.
Definition fp_mul.h:185
uint32_t fp_mulu(uint32_t u, uint32_t v, uint_fast8_t shift)
64-bit implementation of an unsigned multiplication with fixed point format.
Definition fp_mul.h:116
void muldwu(uint32_t w[], uint32_t u, uint32_t v)
Long multiplication of two unsigned 32-bit into an 64-bit value on 32-bit architecture.
Definition fp_mul.h:76