/src/arduinojson/src/ArduinoJson/Numbers/FloatParts.hpp
Line | Count | Source |
1 | | // ArduinoJson - https://arduinojson.org |
2 | | // Copyright © 2014-2026, Benoit BLANCHON |
3 | | // MIT License |
4 | | |
5 | | #pragma once |
6 | | |
7 | | #include <ArduinoJson/Configuration.hpp> |
8 | | #include <ArduinoJson/Numbers/FloatTraits.hpp> |
9 | | #include <ArduinoJson/Numbers/JsonFloat.hpp> |
10 | | #include <ArduinoJson/Polyfills/math.hpp> |
11 | | |
12 | | ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE |
13 | | |
14 | | struct FloatParts { |
15 | | uint32_t integral; |
16 | | uint32_t decimal; |
17 | | int16_t exponent; |
18 | | int8_t decimalPlaces; |
19 | | }; |
20 | | |
21 | | template <typename TFloat> |
22 | 6.36k | inline int16_t normalize(TFloat& value) { |
23 | 6.36k | using traits = FloatTraits<TFloat>; |
24 | 6.36k | int16_t powersOf10 = 0; |
25 | | |
26 | 6.36k | int8_t index = sizeof(TFloat) == 8 ? 8 : 5; |
27 | 6.36k | int bit = 1 << index; |
28 | | |
29 | 6.36k | if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) { |
30 | 15.6k | for (; index >= 0; index--) { |
31 | 14.0k | if (value >= traits::positiveBinaryPowersOfTen()[uint8_t(index)]) { |
32 | 6.04k | value *= traits::negativeBinaryPowersOfTen()[uint8_t(index)]; |
33 | 6.04k | powersOf10 = int16_t(powersOf10 + bit); |
34 | 6.04k | } |
35 | 14.0k | bit >>= 1; |
36 | 14.0k | } |
37 | 1.56k | } |
38 | | |
39 | 6.36k | if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) { |
40 | 4.17k | for (; index >= 0; index--) { |
41 | 3.75k | if (value < traits::negativeBinaryPowersOfTen()[uint8_t(index)] * 10) { |
42 | 877 | value *= traits::positiveBinaryPowersOfTen()[uint8_t(index)]; |
43 | 877 | powersOf10 = int16_t(powersOf10 - bit); |
44 | 877 | } |
45 | 3.75k | bit >>= 1; |
46 | 3.75k | } |
47 | 417 | } |
48 | | |
49 | 6.36k | return powersOf10; |
50 | 6.36k | } |
51 | | |
52 | 48.5k | constexpr uint32_t pow10(int exponent) { |
53 | 48.5k | return (exponent == 0) ? 1 : 10 * pow10(exponent - 1); |
54 | 48.5k | } |
55 | | |
56 | 6.36k | inline FloatParts decomposeFloat(JsonFloat value, int8_t decimalPlaces) { |
57 | 6.36k | uint32_t maxDecimalPart = pow10(decimalPlaces); |
58 | | |
59 | 6.36k | int16_t exponent = normalize(value); |
60 | | |
61 | 6.36k | uint32_t integral = uint32_t(value); |
62 | | // reduce number of decimal places by the number of integral places |
63 | 8.61k | for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) { |
64 | 2.25k | maxDecimalPart /= 10; |
65 | 2.25k | decimalPlaces--; |
66 | 2.25k | } |
67 | | |
68 | 6.36k | JsonFloat remainder = |
69 | 6.36k | (value - JsonFloat(integral)) * JsonFloat(maxDecimalPart); |
70 | | |
71 | 6.36k | uint32_t decimal = uint32_t(remainder); |
72 | 6.36k | remainder = remainder - JsonFloat(decimal); |
73 | | |
74 | | // rounding: |
75 | | // increment by 1 if remainder >= 0.5 |
76 | 6.36k | decimal += uint32_t(remainder * 2); |
77 | 6.36k | if (decimal >= maxDecimalPart) { |
78 | 665 | decimal = 0; |
79 | 665 | integral++; |
80 | 665 | if (exponent && integral >= 10) { |
81 | 237 | exponent++; |
82 | 237 | integral = 1; |
83 | 237 | } |
84 | 665 | } |
85 | | |
86 | | // remove trailing zeros |
87 | 44.2k | while (decimal % 10 == 0 && decimalPlaces > 0) { |
88 | 37.8k | decimal /= 10; |
89 | 37.8k | decimalPlaces--; |
90 | 37.8k | } |
91 | | |
92 | 6.36k | return {integral, decimal, exponent, decimalPlaces}; |
93 | 6.36k | } |
94 | | |
95 | | ARDUINOJSON_END_PRIVATE_NAMESPACE |