libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
writer_float_fixed.hpp
1#pragma once
2
15inline bool Writer::FormatF32FixedPrecText(float value, uint8_t precision, char* out,
16 size_t& out_size)
17{
18 out_size = 0;
19
20 if (std::isnan(value))
21 {
22 return AppendBufferText(out, float_buffer_capacity, out_size, "nan");
23 }
24 if (std::isinf(value))
25 {
26 return AppendBufferText(out, float_buffer_capacity, out_size, "inf");
27 }
28
29 if (precision < f32_decimal_scales_u32.size() && value < f32_u32_overflow_limit)
30 {
31 uint32_t integer_part = static_cast<uint32_t>(value);
32 uint32_t scale = f32_decimal_scales_u32[precision];
33 uint64_t scaled_total = RoundScaledF32(value, scale);
34 uint64_t scaled_integer = static_cast<uint64_t>(integer_part) * scale;
35 uint32_t fractional_part =
36 (scaled_total >= scaled_integer)
37 ? static_cast<uint32_t>(scaled_total - scaled_integer)
38 : 0U;
39
40 if (fractional_part >= scale)
41 {
42 fractional_part -= scale;
43 if (integer_part == std::numeric_limits<uint32_t>::max())
44 {
45 if (!AppendBufferText(out, float_buffer_capacity, out_size, "4294967296"))
46 {
47 return false;
48 }
49 if (precision == 0)
50 {
51 return true;
52 }
53 if (!AppendBufferChar(out, float_buffer_capacity, out_size, '.'))
54 {
55 return false;
56 }
57 for (uint8_t i = 0; i < precision; ++i)
58 {
59 if (!AppendBufferChar(out, float_buffer_capacity, out_size, '0'))
60 {
61 return false;
62 }
63 }
64 return true;
65 }
66 ++integer_part;
67 }
68
69 if (!AppendBufferU32ZeroPad(out, float_buffer_capacity, out_size, integer_part, 1))
70 {
71 return false;
72 }
73 if (precision == 0)
74 {
75 return true;
76 }
77 if (!AppendBufferChar(out, float_buffer_capacity, out_size, '.'))
78 {
79 return false;
80 }
81 return AppendBufferU32ZeroPad(out, float_buffer_capacity, out_size, fractional_part,
82 precision);
83 }
84
85 float rounded = value;
86 float rounding = 0.5f;
87 for (uint8_t i = 0; i < precision; ++i)
88 {
89 rounding *= 0.1f;
90 }
91 rounded += rounding;
92
93 if (rounded < 1.0f)
94 {
95 if (!AppendBufferChar(out, float_buffer_capacity, out_size, '0'))
96 {
97 return false;
98 }
99 }
100 else
101 {
102 float integer_scale = 1.0f;
103 while (true)
104 {
105 float next_scale = integer_scale * 10.0f;
106 if (!std::isfinite(next_scale) || rounded < next_scale)
107 {
108 break;
109 }
110 integer_scale = next_scale;
111 }
112
113 while (integer_scale >= 1.0f)
114 {
115 int digit = static_cast<int>(rounded / integer_scale);
116 if (digit < 0)
117 {
118 digit = 0;
119 }
120 else if (digit > 9)
121 {
122 digit = 9;
123 }
124
125 if (!AppendBufferChar(out, float_buffer_capacity, out_size,
126 static_cast<char>('0' + digit)))
127 {
128 return false;
129 }
130
131 rounded -= static_cast<float>(digit) * integer_scale;
132 float epsilon = integer_scale * 1e-6f;
133 if (rounded < 0.0f && rounded > -epsilon)
134 {
135 rounded = 0.0f;
136 }
137 integer_scale *= 0.1f;
138 }
139 }
140
141 if (precision == 0)
142 {
143 return true;
144 }
145 if (!AppendBufferChar(out, float_buffer_capacity, out_size, '.'))
146 {
147 return false;
148 }
149
150 for (uint8_t i = 0; i < precision; ++i)
151 {
152 rounded *= 10.0f;
153 int digit = static_cast<int>(rounded + 1e-6f);
154 if (digit < 0)
155 {
156 digit = 0;
157 }
158 else if (digit > 9)
159 {
160 digit = 9;
161 }
162
163 if (!AppendBufferChar(out, float_buffer_capacity, out_size,
164 static_cast<char>('0' + digit)))
165 {
166 return false;
167 }
168
169 rounded -= static_cast<float>(digit);
170 if (rounded < 0.0f && rounded > -1e-5f)
171 {
172 rounded = 0.0f;
173 }
174 }
175
176 return true;
177}
178
189template <typename Float>
190bool Writer::FormatFixedText(Float value, uint8_t precision, bool alternate, char* out,
191 size_t& out_size)
192{
193 Float rounded =
194 value + static_cast<Float>(0.5L) * Power10<Float>(-static_cast<int>(precision));
195 auto normalized = NormalizeDecimal(rounded);
196 int integer_exponent = (rounded == 0) ? 0 : normalized.exponent;
197 int start_pos = (integer_exponent > 0) ? integer_exponent : 0;
198 Float scale = Power10<Float>(start_pos);
199
200 out_size = 0;
201 for (int pos = start_pos; pos >= 0; --pos)
202 {
203 if (!AppendBufferChar(out, float_buffer_capacity, out_size,
204 static_cast<char>('0' + ExtractDigit(rounded, scale))))
205 {
206 return false;
207 }
208 scale /= 10;
209 }
210
211 if (precision != 0 || alternate)
212 {
213 if (!AppendBufferChar(out, float_buffer_capacity, out_size, '.'))
214 {
215 return false;
216 }
217 }
218
219 for (uint8_t i = 0; i < precision; ++i)
220 {
221 if (!AppendBufferChar(out, float_buffer_capacity, out_size,
222 static_cast<char>('0' + ExtractDigit(rounded, scale))))
223 {
224 return false;
225 }
226 scale /= 10;
227 }
228
229 return true;
230}