-
Notifications
You must be signed in to change notification settings - Fork 0
/
arm_inlines_float.h
89 lines (69 loc) · 2.93 KB
/
arm_inlines_float.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*!\file arm_inlines_float.h
** \author SMFSW
** \copyright MIT (c) 2017-2024, SMFSW
** \brief Floating point manipulation inlines
*/
/****************************************************************/
#ifndef ARM_INLINES_FLOAT_H_
#define ARM_INLINES_FLOAT_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <math.h>
/****************************************************************/
//!< \warning Sign does not work for values between 0 and -1 (sign is lost)
#define SPLIT_FLOAT_TO_INTS(val, nb_frac) (SDWORD) (val), get_fp_dec((val), (nb_frac)) //!< Split float value \p val into 2 integers with \b nb_frac fractional part digits
/*!\struct sIntFrac
** \brief Float representation on integers
**/
typedef struct sIntFrac {
DWORD integer; //!< Integer part
DWORD fractionnal; //!< Fractional part
BYTE nb_frac; //!< Number of fractional digits
BOOL sign; //!< Sign: true if negative
} sIntFrac;
/*!\brief Get floating point number decimal part (as absolute value)
** \note if in need to print floats, you can add '-u _printf_float' in Linker options instead of using get_fp_dec.
** Otherwise, \ref SPLIT_FLOAT_TO_INTS may be used to ease the formatting process for printf like functions.
** \param[in] f - floating point value
** \param[in] nb - Number of decimal to get after floating point (limited to 9 internally for proper result on 32b return type)
** \return nb decimal part as unsigned integer
**/
__INLINE DWORD get_fp_dec(const double f, const BYTE nb)
{
BYTE digits = MIN(9, nb); // Limit to 9 digits
DWORD mul = 1;
while (digits-- > 0) { mul *= 10; }
double dec = fabs(f);
dec -= (double) ((DWORD) f);
return (DWORD) (dec * (double) mul);
}
/*!\brief Convert floating point representation to sIntFrac integers representation
** \param[in,out] pIntFrac - Pointer to result structure
** \param[in] f - floating point value to convert
** \param[in] nb_frac - Number of decimal to get after floating point (limited to 9 internally for proper result on 32b return type)
**/
__INLINE void NONNULL__ float2sIntFrac(sIntFrac * const pIntFrac, const double f, const uint8_t nb_frac)
{
pIntFrac->nb_frac = MIN(9, nb_frac); // Limit to 9 digits
pIntFrac->sign = binEval(f < 0.0);
pIntFrac->integer = (DWORD) (f);
pIntFrac->fractionnal = get_fp_dec(f, nb_frac);
}
/*!\brief Convert sIntFrac integers representation to floating point representation
** \param[in,out] pFloat - Pointer to floating point result
** \param[in] pIntFrac - Pointer to sIntFrac structure to convert
**/
__INLINE void NONNULL__ sIntFrac2float(double * const pFloat, const sIntFrac * const pIntFrac)
{
*pFloat = pIntFrac->fractionnal;
for (uintCPU_t i = pIntFrac->nb_frac ; i ; i--) { *pFloat /= 10.0; }
*pFloat += pIntFrac->integer;
if (pIntFrac->sign) { *pFloat = -*pFloat; }
}
/****************************************************************/
#ifdef __cplusplus
}
#endif
#endif /* ARM_INLINES_FLOAT_H_ */
/****************************************************************/