Branch data Line data Source code
1 : : /*
2 : : * This file is part of the MicroPython project, http://micropython.org/
3 : : *
4 : : * The MIT License (MIT)
5 : : *
6 : : * Copyright (c) 2013, 2014 Damien P. George
7 : : *
8 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : * of this software and associated documentation files (the "Software"), to deal
10 : : * in the Software without restriction, including without limitation the rights
11 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : * copies of the Software, and to permit persons to whom the Software is
13 : : * furnished to do so, subject to the following conditions:
14 : : *
15 : : * The above copyright notice and this permission notice shall be included in
16 : : * all copies or substantial portions of the Software.
17 : : *
18 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 : : * THE SOFTWARE.
25 : : */
26 : :
27 : : #include "py/mpconfig.h"
28 : : #include "py/misc.h"
29 : : #if MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE
30 : :
31 : : #include <assert.h>
32 : : #include <stdlib.h>
33 : : #include <stdint.h>
34 : : #include <math.h>
35 : : #include "py/formatfloat.h"
36 : :
37 : : /***********************************************************************
38 : :
39 : : Routine for converting a arbitrary floating
40 : : point number into a string.
41 : :
42 : : The code in this function was inspired from Fred Bayer's pdouble.c.
43 : : Since pdouble.c was released as Public Domain, I'm releasing this
44 : : code as public domain as well.
45 : :
46 : : The original code can be found in https://github.com/dhylands/format-float
47 : :
48 : : Dave Hylands
49 : :
50 : : ***********************************************************************/
51 : :
52 : : #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
53 : : // 1 sign bit, 8 exponent bits, and 23 mantissa bits.
54 : : // exponent values 0 and 255 are reserved, exponent can be 1 to 254.
55 : : // exponent is stored with a bias of 127.
56 : : // The min and max floats are on the order of 1x10^37 and 1x10^-37
57 : :
58 : : #define FPTYPE float
59 : : #define FPCONST(x) x##F
60 : : #define FPROUND_TO_ONE 0.9999995F
61 : : #define FPDECEXP 32
62 : : #define FPMIN_BUF_SIZE 6 // +9e+99
63 : :
64 : : #define FLT_SIGN_MASK 0x80000000
65 : :
66 : : static inline int fp_signbit(float x) {
67 : : mp_float_union_t fb = {x};
68 : : return fb.i & FLT_SIGN_MASK;
69 : : }
70 : : #define fp_isnan(x) isnan(x)
71 : : #define fp_isinf(x) isinf(x)
72 : : static inline int fp_iszero(float x) {
73 : : mp_float_union_t fb = {x};
74 : : return fb.i == 0;
75 : : }
76 : : static inline int fp_isless1(float x) {
77 : : mp_float_union_t fb = {x};
78 : : return fb.i < 0x3f800000;
79 : : }
80 : :
81 : : #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
82 : :
83 : : #define FPTYPE double
84 : : #define FPCONST(x) x
85 : : #define FPROUND_TO_ONE 0.999999999995
86 : : #define FPDECEXP 256
87 : : #define FPMIN_BUF_SIZE 7 // +9e+199
88 : : #define fp_signbit(x) signbit(x)
89 : : #define fp_isnan(x) isnan(x)
90 : : #define fp_isinf(x) isinf(x)
91 : : #define fp_iszero(x) (x == 0)
92 : : #define fp_isless1(x) (x < 1.0)
93 : :
94 : : #endif // MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT/DOUBLE
95 : :
96 : 42556 : static inline int fp_expval(FPTYPE x) {
97 : 42556 : mp_float_union_t fb = {x};
98 : 42556 : return (int)((fb.i >> MP_FLOAT_FRAC_BITS) & (~(0xFFFFFFFF << MP_FLOAT_EXP_BITS))) - MP_FLOAT_EXP_OFFSET;
99 : : }
100 : :
101 : 45094 : int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) {
102 : :
103 : 45094 : char *s = buf;
104 : :
105 [ + + ]: 45094 : if (buf_size <= FPMIN_BUF_SIZE) {
106 : : // FPMIN_BUF_SIZE is the minimum size needed to store any FP number.
107 : : // If the buffer does not have enough room for this (plus null terminator)
108 : : // then don't try to format the float.
109 : :
110 [ + - ]: 2 : if (buf_size >= 2) {
111 : 2 : *s++ = '?';
112 : : }
113 [ + - ]: 2 : if (buf_size >= 1) {
114 : 2 : *s = '\0';
115 : : }
116 : 2 : return buf_size >= 2;
117 : : }
118 [ + + + + ]: 45092 : if (fp_signbit(f) && !fp_isnan(f)) {
119 : 8872 : *s++ = '-';
120 : 8872 : f = -f;
121 : : } else {
122 [ + + ]: 36220 : if (sign) {
123 : 12 : *s++ = sign;
124 : : }
125 : : }
126 : :
127 : : // buf_remaining contains bytes available for digits and exponent.
128 : : // It is buf_size minus room for the sign and null byte.
129 : 45092 : int buf_remaining = buf_size - 1 - (s - buf);
130 : :
131 : : {
132 : 45092 : char uc = fmt & 0x20;
133 [ + + ]: 45092 : if (fp_isinf(f)) {
134 : 1532 : *s++ = 'I' ^ uc;
135 : 1532 : *s++ = 'N' ^ uc;
136 : 1532 : *s++ = 'F' ^ uc;
137 : 1532 : goto ret;
138 [ + + ]: 43560 : } else if (fp_isnan(f)) {
139 : 1004 : *s++ = 'N' ^ uc;
140 : 1004 : *s++ = 'A' ^ uc;
141 : 1004 : *s++ = 'N' ^ uc;
142 : 2536 : ret:
143 : 2536 : *s = '\0';
144 : 2536 : return s - buf;
145 : : }
146 : : }
147 : :
148 [ + + ]: 42556 : if (prec < 0) {
149 : 104 : prec = 6;
150 : : }
151 : 42556 : char e_char = 'E' | (fmt & 0x20); // e_char will match case of fmt
152 : 42556 : fmt |= 0x20; // Force fmt to be lowercase
153 : 42556 : char org_fmt = fmt;
154 [ + + ]: 42556 : if (fmt == 'g' && prec == 0) {
155 : 6 : prec = 1;
156 : : }
157 : 42556 : int e;
158 : 42556 : int dec = 0;
159 : 42556 : char e_sign = '\0';
160 : 42556 : int num_digits = 0;
161 : 42556 : int signed_e = 0;
162 : :
163 : : // Approximate power of 10 exponent from binary exponent.
164 : : // abs(e_guess) is lower bound on abs(power of 10 exponent).
165 : 42556 : int e_guess = (int)(fp_expval(f) * FPCONST(0.3010299956639812)); // 1/log2(10).
166 [ + + ]: 42556 : if (fp_iszero(f)) {
167 : 3122 : e = 0;
168 [ + + ]: 3122 : if (fmt == 'f') {
169 : : // Truncate precision to prevent buffer overflow
170 [ + + ]: 2230 : if (prec + 2 > buf_remaining) {
171 : 12 : prec = buf_remaining - 2;
172 : : }
173 : 2230 : num_digits = prec + 1;
174 : : } else {
175 : : // Truncate precision to prevent buffer overflow
176 [ + + ]: 892 : if (prec + 6 > buf_remaining) {
177 : 40 : prec = buf_remaining - 6;
178 : : }
179 [ + + ]: 892 : if (fmt == 'e') {
180 : 28 : e_sign = '+';
181 : : }
182 : : }
183 [ + + ]: 39434 : } else if (fp_isless1(f)) {
184 : 16610 : FPTYPE f_entry = f; // Save f in case we go to 'f' format.
185 : : // Build negative exponent
186 : 16610 : e = -e_guess;
187 : 16610 : FPTYPE u_base = MICROPY_FLOAT_C_FUN(pow)(10, -e);
188 [ + + ]: 23620 : while (u_base > f) {
189 : 7010 : ++e;
190 : 7010 : u_base = MICROPY_FLOAT_C_FUN(pow)(10, -e);
191 : : }
192 : : // Normalize out the inferred unit. Use divide because
193 : : // pow(10, e) * pow(10, -e) is slightly < 1 for some e in float32
194 : : // (e.g. print("%.12f" % ((1e13) * (1e-13))))
195 : 16610 : f /= u_base;
196 : :
197 : : // If the user specified 'g' format, and e is <= 4, then we'll switch
198 : : // to the fixed format ('f')
199 : :
200 [ + + + + ]: 16610 : if (fmt == 'f' || (fmt == 'g' && e <= 4)) {
201 : 12776 : fmt = 'f';
202 : 12776 : dec = 0;
203 : :
204 : 2306 : if (org_fmt == 'g') {
205 : 2306 : prec += (e - 1);
206 : : }
207 : :
208 : : // truncate precision to prevent buffer overflow
209 [ + + ]: 10470 : if (prec + 2 > buf_remaining) {
210 : 1456 : prec = buf_remaining - 2;
211 : : }
212 : :
213 : 10470 : num_digits = prec;
214 : 10470 : signed_e = 0;
215 : 10470 : f = f_entry;
216 : 10470 : ++num_digits;
217 : : } else {
218 : : // For e & g formats, we'll be printing the exponent, so set the
219 : : // sign.
220 : 6140 : e_sign = '-';
221 : 6140 : dec = 0;
222 : :
223 [ + + ]: 6140 : if (prec > (buf_remaining - FPMIN_BUF_SIZE)) {
224 : 5040 : prec = buf_remaining - FPMIN_BUF_SIZE;
225 [ + + ]: 5040 : if (fmt == 'g') {
226 : 2424 : prec++;
227 : : }
228 : : }
229 : 6140 : signed_e = -e;
230 : : }
231 : : } else {
232 : : // Build positive exponent.
233 : : // We don't modify f at this point to avoid inaccuracies from
234 : : // scaling it. Instead, we find the product of powers of 10
235 : : // that is not greater than it, and use that to start the
236 : : // mantissa.
237 : 22824 : e = e_guess;
238 : 22824 : FPTYPE next_u = MICROPY_FLOAT_C_FUN(pow)(10, e + 1);
239 [ + + ]: 34534 : while (f >= next_u) {
240 : 11710 : ++e;
241 : 11710 : next_u = MICROPY_FLOAT_C_FUN(pow)(10, e + 1);
242 : : }
243 : :
244 : : // If the user specified fixed format (fmt == 'f') and e makes the
245 : : // number too big to fit into the available buffer, then we'll
246 : : // switch to the 'e' format.
247 : :
248 [ + + ]: 22824 : if (fmt == 'f') {
249 [ + + ]: 10084 : if (e >= buf_remaining) {
250 : : fmt = 'e';
251 [ + + ]: 8092 : } else if ((e + prec + 2) > buf_remaining) {
252 : 964 : prec = buf_remaining - e - 2;
253 [ + + ]: 964 : if (prec < 0) {
254 : : // This means no decimal point, so we can add one back
255 : : // for the decimal.
256 : 28 : prec++;
257 : : }
258 : : }
259 : : }
260 [ + + + + ]: 22824 : if (fmt == 'e' && prec > (buf_remaining - FPMIN_BUF_SIZE)) {
261 : 4346 : prec = buf_remaining - FPMIN_BUF_SIZE;
262 : : }
263 [ + + ]: 22824 : if (fmt == 'g') {
264 : : // Truncate precision to prevent buffer overflow
265 [ + + ]: 8846 : if (prec + (FPMIN_BUF_SIZE - 1) > buf_remaining) {
266 : 2202 : prec = buf_remaining - (FPMIN_BUF_SIZE - 1);
267 : : }
268 : : }
269 : : // If the user specified 'g' format, and e is < prec, then we'll switch
270 : : // to the fixed format.
271 : :
272 [ + + ]: 22824 : if (fmt == 'g' && e < prec) {
273 : 5016 : fmt = 'f';
274 : 5016 : prec -= (e + 1);
275 : : }
276 [ + + ]: 22824 : if (fmt == 'f') {
277 : 13108 : dec = e;
278 : 13108 : num_digits = prec + e + 1;
279 : : } else {
280 : : e_sign = '+';
281 : : }
282 : : signed_e = e;
283 : : }
284 [ + + ]: 42556 : if (prec < 0) {
285 : : // This can happen when the prec is trimmed to prevent buffer overflow
286 : 2 : prec = 0;
287 : : }
288 : :
289 : : // At this point e contains the absolute value of the power of 10 exponent.
290 : : // (dec + 1) == the number of dgits before the decimal.
291 : :
292 : : // For e, prec is # digits after the decimal
293 : : // For f, prec is # digits after the decimal
294 : : // For g, prec is the max number of significant digits
295 : : //
296 : : // For e & g there will be a single digit before the decimal
297 : : // for f there will be e digits before the decimal
298 : :
299 [ + + ]: 42556 : if (fmt == 'e') {
300 : 9134 : num_digits = prec + 1;
301 [ + + ]: 33422 : } else if (fmt == 'g') {
302 [ + + ]: 7614 : if (prec == 0) {
303 : 2 : prec = 1;
304 : : }
305 : : num_digits = prec;
306 : : }
307 : :
308 : 42556 : int d = 0;
309 [ + + ]: 758974 : for (int digit_index = signed_e; num_digits >= 0; --digit_index) {
310 : 716418 : FPTYPE u_base = FPCONST(1.0);
311 [ + + ]: 716418 : if (digit_index > 0) {
312 : : // Generate 10^digit_index for positive digit_index.
313 : 227574 : u_base = MICROPY_FLOAT_C_FUN(pow)(10, digit_index);
314 : : }
315 [ + + ]: 1140361 : for (d = 0; d < 9; ++d) {
316 [ + + ]: 1125189 : if (f < u_base) {
317 : : break;
318 : : }
319 : 423943 : f -= u_base;
320 : : }
321 : : // We calculate one more digit than we display, to use in rounding
322 : : // below. So only emit the digit if it's one that we display.
323 [ + + ]: 716418 : if (num_digits > 0) {
324 : : // Emit this number (the leading digit).
325 : 673862 : *s++ = '0' + d;
326 [ + + ]: 673862 : if (dec == 0 && prec > 0) {
327 : 42214 : *s++ = '.';
328 : : }
329 : : }
330 : 716418 : --dec;
331 : 716418 : --num_digits;
332 [ + + ]: 716418 : if (digit_index <= 0) {
333 : : // Once we get below 1.0, we scale up f instead of calculating
334 : : // negative powers of 10 in u_base. This provides better
335 : : // renditions of exact decimals like 1/16 etc.
336 : 488844 : f *= FPCONST(10.0);
337 : : }
338 : : }
339 : : // Rounding. If the next digit to print is >= 5, round up.
340 [ + + ]: 42556 : if (d >= 5) {
341 : 5130 : char *rs = s;
342 : 5130 : rs--;
343 : 14710 : while (1) {
344 [ + + ]: 14710 : if (*rs == '.') {
345 : 254 : rs--;
346 : 254 : continue;
347 : : }
348 [ + + ]: 14456 : if (*rs < '0' || *rs > '9') {
349 : : // + or -
350 : 4 : rs++; // So we sit on the digit to the right of the sign
351 : 4 : break;
352 : : }
353 [ + + ]: 14452 : if (*rs < '9') {
354 : 4938 : (*rs)++;
355 : 4938 : break;
356 : : }
357 : 9514 : *rs = '0';
358 [ + + ]: 9514 : if (rs == buf) {
359 : : break;
360 : : }
361 : 9326 : rs--;
362 : : }
363 [ + + ]: 5130 : if (*rs == '0') {
364 : : // We need to insert a 1
365 [ + + + - ]: 192 : if (rs[1] == '.' && fmt != 'f') {
366 : : // We're going to round 9.99 to 10.00
367 : : // Move the decimal point
368 : 128 : rs[0] = '.';
369 : 128 : rs[1] = '0';
370 [ + + ]: 128 : if (e_sign == '-') {
371 : 4 : e--;
372 [ + - ]: 4 : if (e == 0) {
373 : 4 : e_sign = '+';
374 : : }
375 : : } else {
376 : 124 : e++;
377 : : }
378 : : } else {
379 : : // Need at extra digit at the end to make room for the leading '1'
380 : : // but if we're at the buffer size limit, just drop the final digit.
381 [ + + ]: 64 : if ((size_t)(s + 1 - buf) < buf_size) {
382 : 36 : s++;
383 : : }
384 : : }
385 : 192 : char *ss = s;
386 [ + + ]: 4772 : while (ss > rs) {
387 : 4580 : *ss = ss[-1];
388 : 4580 : ss--;
389 : : }
390 : 192 : *rs = '1';
391 : : }
392 : : }
393 : :
394 : : // verify that we did not overrun the input buffer so far
395 [ - + ]: 42556 : assert((size_t)(s + 1 - buf) <= buf_size);
396 : :
397 [ + + ]: 42556 : if (org_fmt == 'g' && prec > 0) {
398 : : // Remove trailing zeros and a trailing decimal point
399 [ + + ]: 195570 : while (s[-1] == '0') {
400 : 180882 : s--;
401 : : }
402 [ + + ]: 14688 : if (s[-1] == '.') {
403 : 9966 : s--;
404 : : }
405 : : }
406 : : // Append the exponent
407 [ + + ]: 42556 : if (e_sign) {
408 : 15884 : *s++ = e_char;
409 : 15884 : *s++ = e_sign;
410 [ + + ]: 15884 : if (FPMIN_BUF_SIZE == 7 && e >= 100) {
411 : 1132 : *s++ = '0' + (e / 100);
412 : : }
413 : 15884 : *s++ = '0' + ((e / 10) % 10);
414 : 15884 : *s++ = '0' + (e % 10);
415 : : }
416 : 42556 : *s = '\0';
417 : :
418 : : // verify that we did not overrun the input buffer
419 [ - + ]: 42556 : assert((size_t)(s + 1 - buf) <= buf_size);
420 : :
421 : 42556 : return s - buf;
422 : : }
423 : :
424 : : #endif // MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE
|