AFBR-S50 API Reference Manual v1.5.6
AFBR-S50 Time-of-Flight Sensor SDK for Embedded Software
Loading...
Searching...
No Matches
fp_div.h
Go to the documentation of this file.
1/*************************************************************************/
37#ifndef FP_DIV_H
38#define FP_DIV_H
39#ifdef __cplusplus
40extern "C" {
41#endif
42
43/*!***************************************************************************
44 * @addtogroup argus_fp
45 * @{
46 *****************************************************************************/
47
48#include "fp_def.h"
49#include "int_math.h"
50
51/*!***************************************************************************
52 * Set to use hardware division (Cortex-M3/4) over software division (Cortex-M0/1).
53 *****************************************************************************/
54#ifndef USE_HW_DIV
55#define USE_HW_DIV 0
56#endif
57
58/*!***************************************************************************
59 * @brief 32-bit implementation of an Q15.16 division.
60 *
61 * @details Algorithm to evaluate a/b, where b is in Q15.16 format, on a 32-bit
62 * architecture with maximum precision.
63 * The result is correctly rounded and given as the input format.
64 * Division by 0 yields max. values determined by signs of numerator.
65 * Too high/low results are truncated to max/min values.
66 *
67 * Depending on the architecture, the division is implemented with a 64-bit
68 * division and shifting (Cortex-M3/4) or as a fast software algorithm
69 * (Cortex-M0/1) wich runs fast on processors without hardware division.
70 *
71 * @see https://code.google.com/archive/p/libfixmath
72 *
73 * @param a Numerator in any Qx.y format
74 * @param b Denominator in Q15.16 format
75 * @return Result = a/b in the same Qx.y format as the input parameter a.
76 *****************************************************************************/
77inline int32_t fp_div16(int32_t a, q15_16_t b)
78{
79 //assert(b);
80 if (b == 0) return a < 0 ? INT32_MIN : INT32_MAX;
81
82#if USE_HW_DIV
83 // Tested on Cortex-M4, it takes approx. 75% of the
84 // software algorithm below.
85 int64_t c = ((int64_t) a) << 30U;
86 if ((uint32_t) (a ^ b) & 0x80000000U)
87 {
88 c = (((-c) / b) + (1 << 13U)) >> 14U;
89 if (c > 0x80000000U) return INT32_MIN;
90 return (int32_t)-c;
91 }
92 else
93 {
94 c = ((c / b) + (1 << 13U)) >> 14U;
95 if (c > (int64_t)INT32_MAX) return INT32_MAX;
96 return (int32_t)c;
97 }
98
99#else
100 // This uses the basic binary restoring division algorithm.
101 // It appears to be faster to do the whole division manually than
102 // trying to compose a 64-bit divide out of 32-bit divisions on
103 // platforms without hardware divide.
104 // Tested on Cortex-M0, it takes approx. 33% of the time of the
105 // 64-bit version above.
106
107 uint32_t remainder = absval(a);
108 uint32_t divider = absval(b);
109
110 uint32_t quotient = 0;
111 uint32_t bit = 0x10000U;
112
113 /* The algorithm requires D >= R */
114 while (divider < remainder)
115 {
116 divider <<= 1U;
117 bit <<= 1U;
118 }
119
120 if (!bit)
121 {
122 if ((uint32_t)(a ^ b) & 0x80000000U) // return truncated values
123 {
124 return INT32_MIN;
125 }
126 else
127 {
128 return INT32_MAX;
129 }
130 }
131
132 if (divider & 0x80000000U)
133 {
134 // Perform one step manually to avoid overflows later.
135 // We know that divider's bottom bit is 0 here.
136 if (remainder >= divider)
137 {
138 quotient |= bit;
139 remainder -= divider;
140 }
141 divider >>= 1U;
142 bit >>= 1U;
143 }
144
145 /* Main division loop */
146 while (bit && remainder)
147 {
148 if (remainder >= divider)
149 {
150 quotient |= bit;
151 remainder -= divider;
152 }
153 remainder <<= 1U;
154 bit >>= 1U;
155 }
156
157 if (remainder >= divider)
158 {
159 quotient++;
160 }
161
162 uint32_t result = quotient;
163
164 /* Figure out the sign of result */
165 if ((uint32_t)(a ^ b) & 0x80000000U)
166 {
167 return (int32_t)-result;
168 }
169 else
170 {
171 // fix 05.10.2023; the corner case, when result == INT32_MAX + 1:
172 // Catch the wraparound (to INT32_MIN) and truncate instead.
173 if (quotient > INT32_MAX) return INT32_MAX;
174 return (int32_t)result;
175 }
176
177#endif
178}
179
181#ifdef __cplusplus
182} // extern "C"
183#endif
184#endif /* FP_DIV_H */
This file is part of the AFBR-S50 API.
int32_t fp_div16(int32_t a, q15_16_t b)
32-bit implementation of an Q15.16 division.
Definition fp_div.h:77
int32_t q15_16_t
Signed fixed point number: Q15.16.
Definition fp_def.h:515
uint32_t absval(int32_t x)
Calculates the absolute value.
Definition int_math.h:155
This file is part of the AFBR-S50 API.