libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
writer_float_math.hpp
1#pragma once
2
13inline uint64_t Writer::RoundScaledF32(float value, uint32_t scale)
14{
15 uint32_t bits = std::bit_cast<uint32_t>(value);
16 uint32_t exponent_bits = (bits >> 23) & 0xFFU;
17 uint32_t fraction_bits = bits & 0x7FFFFFU;
18 uint32_t significand =
19 (exponent_bits == 0) ? fraction_bits : ((1U << 23) | fraction_bits);
20 int exponent2 =
21 (exponent_bits == 0) ? -149 : static_cast<int>(exponent_bits) - 150;
22 uint64_t numerator = static_cast<uint64_t>(significand) * scale;
23
24 if (exponent2 >= 0)
25 {
26 return numerator << exponent2;
27 }
28
29 unsigned int shift = static_cast<unsigned int>(-exponent2);
30 if (shift >= 64)
31 {
32 return 0;
33 }
34 uint64_t quotient = numerator >> shift;
35 uint64_t remainder = numerator & ((uint64_t{1} << shift) - 1U);
36 uint64_t halfway = uint64_t{1} << (shift - 1);
37 if (remainder > halfway || (remainder == halfway && (quotient & 1U) != 0U))
38 {
39 ++quotient;
40 }
41 return quotient;
42}
43
48template <typename Float>
50{
51 int exponent = 0;
52 Float scale = 1;
53};
54
61template <typename Float>
62Float Writer::Power10(int exponent)
63{
64 Float result = 1;
65 Float base = 10;
66 unsigned int remaining =
67 static_cast<unsigned int>(exponent < 0 ? -exponent : exponent);
68
69 while (remaining != 0)
70 {
71 if ((remaining & 1U) != 0U)
72 {
73 if (exponent < 0)
74 {
75 result /= base;
76 }
77 else
78 {
79 result *= base;
80 }
81 }
82
83 remaining >>= 1U;
84 if (remaining != 0U)
85 {
86 base *= base;
87 }
88 }
89
90 return result;
91}
92
100template <typename Float>
101Writer::DecimalScale<Float> Writer::NormalizeDecimal(Float value)
102{
103 DecimalScale<Float> normalized{};
104 if (value == 0)
105 {
106 return normalized;
107 }
108
109 int binary_exponent = 0;
110 std::frexp(value, &binary_exponent);
111 constexpr Float log10_of_2 =
112 static_cast<Float>(0.30102999566398119521373889472449L);
113 normalized.exponent =
114 static_cast<int>(static_cast<Float>(binary_exponent - 1) * log10_of_2);
115 normalized.scale = Power10<Float>(normalized.exponent);
116
117 Float scaled = value / normalized.scale;
118 while (scaled < 1)
119 {
120 normalized.scale /= 10;
121 --normalized.exponent;
122 scaled *= 10;
123 }
124 while (scaled >= 10)
125 {
126 normalized.scale *= 10;
127 ++normalized.exponent;
128 scaled /= 10;
129 }
130
131 return normalized;
132}
133
142template <typename Float>
143uint8_t Writer::ExtractDigit(Float& value, Float scale)
144{
145 Float scaled = value / scale;
146 auto digit = static_cast<int>(scaled + static_cast<Float>(1e-12L));
147 if (digit < 0)
148 {
149 digit = 0;
150 }
151 else if (digit > 9)
152 {
153 digit = 9;
154 }
155
156 value -= static_cast<Float>(digit) * scale;
157 Float epsilon = scale * static_cast<Float>(1e-9L);
158 if (value < 0 && value > -epsilon)
159 {
160 value = 0;
161 }
162
163 return static_cast<uint8_t>(digit);
164}
165
172inline size_t Writer::TrimGeneralText(char* text, size_t size)
173{
174 size_t exponent_pos = size;
175 for (size_t i = 0; i < size; ++i)
176 {
177 if (text[i] == 'e' || text[i] == 'E')
178 {
179 exponent_pos = i;
180 break;
181 }
182 }
183
184 size_t mantissa_end = exponent_pos;
185 while (mantissa_end > 0 && text[mantissa_end - 1] == '0')
186 {
187 --mantissa_end;
188 }
189 if (mantissa_end > 0 && text[mantissa_end - 1] == '.')
190 {
191 --mantissa_end;
192 }
193
194 if (exponent_pos == size)
195 {
196 return mantissa_end;
197 }
198
199 std::memmove(text + mantissa_end, text + exponent_pos, size - exponent_pos);
200 return mantissa_end + (size - exponent_pos);
201}
202
211inline bool Writer::AppendExponentText(char* out, size_t& out_size, int exponent,
212 bool upper_case)
213{
214 if (!AppendBufferChar(out, float_buffer_capacity, out_size,
215 upper_case ? 'E' : 'e'))
216 {
217 return false;
218 }
219 if (!AppendBufferChar(out, float_buffer_capacity, out_size,
220 exponent < 0 ? '-' : '+'))
221 {
222 return false;
223 }
224
225 char digits[UnsignedDigitCapacity<unsigned int, 10>()];
226 unsigned int magnitude =
227 static_cast<unsigned int>(exponent < 0 ? -exponent : exponent);
228 size_t digit_count = AppendUnsigned<10>(digits, magnitude);
229 if (digit_count < 2 &&
230 !AppendBufferChar(out, float_buffer_capacity, out_size, '0'))
231 {
232 return false;
233 }
234
235 return AppendBufferText(out, float_buffer_capacity, out_size,
236 std::string_view(digits, digit_count));
237}
浮点文本输出归一化过程中使用的十进制缩放对 / Decimal-scale pair used while normalizing one float for text output.
Float scale
10 ^ exponent / 10 的 exponent 次幂
int exponent
decimal exponent / 十进制指数