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 #if MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE
29 
30 #include <assert.h>
31 #include <stdlib.h>
32 #include <stdint.h>
33 #include <math.h>
34 #include "py/formatfloat.h"
35 
36 /***********************************************************************
37 
38   Routine for converting a arbitrary floating
39   point number into a string.
40 
41   The code in this funcion was inspired from Fred Bayer's pdouble.c.
42   Since pdouble.c was released as Public Domain, I'm releasing this
43   code as public domain as well.
44 
45   The original code can be found in https://github.com/dhylands/format-float
46 
47   Dave Hylands
48 
49 ***********************************************************************/
50 
51 #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
52 // 1 sign bit, 8 exponent bits, and 23 mantissa bits.
53 // exponent values 0 and 255 are reserved, exponent can be 1 to 254.
54 // exponent is stored with a bias of 127.
55 // The min and max floats are on the order of 1x10^37 and 1x10^-37
56 
57 #define FPTYPE float
58 #define FPCONST(x) x##F
59 #define FPROUND_TO_ONE 0.9999995F
60 #define FPDECEXP 32
61 #define FPMIN_BUF_SIZE 6 // +9e+99
62 
63 #define FLT_SIGN_MASK   0x80000000
64 #define FLT_EXP_MASK    0x7F800000
65 #define FLT_MAN_MASK    0x007FFFFF
66 
67 union floatbits {
68     float f;
69     uint32_t u;
70 };
fp_signbit(float x)71 static inline int fp_signbit(float x) {
72     union floatbits fb = {x};
73     return fb.u & FLT_SIGN_MASK;
74 }
75 #define fp_isnan(x) isnan(x)
76 #define fp_isinf(x) isinf(x)
fp_iszero(float x)77 static inline int fp_iszero(float x) {
78     union floatbits fb = {x};
79     return fb.u == 0;
80 }
fp_isless1(float x)81 static inline int fp_isless1(float x) {
82     union floatbits fb = {x};
83     return fb.u < 0x3f800000;
84 }
85 
86 #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
87 
88 #define FPTYPE double
89 #define FPCONST(x) x
90 #define FPROUND_TO_ONE 0.999999999995
91 #define FPDECEXP 256
92 #define FPMIN_BUF_SIZE 7 // +9e+199
93 #define fp_signbit(x) signbit(x)
94 #define fp_isnan(x) isnan(x)
95 #define fp_isinf(x) isinf(x)
96 #define fp_iszero(x) (x == 0)
97 #define fp_isless1(x) (x < 1.0)
98 
99 #endif
100 
101 static const FPTYPE g_pos_pow[] = {
102     #if FPDECEXP > 32
103     MICROPY_FLOAT_CONST(1e256), MICROPY_FLOAT_CONST(1e128), MICROPY_FLOAT_CONST(1e64),
104     #endif
105     MICROPY_FLOAT_CONST(1e32), MICROPY_FLOAT_CONST(1e16), MICROPY_FLOAT_CONST(1e8), MICROPY_FLOAT_CONST(1e4), MICROPY_FLOAT_CONST(1e2), MICROPY_FLOAT_CONST(1e1)
106 };
107 static const FPTYPE g_neg_pow[] = {
108     #if FPDECEXP > 32
109     MICROPY_FLOAT_CONST(1e-256), MICROPY_FLOAT_CONST(1e-128), MICROPY_FLOAT_CONST(1e-64),
110     #endif
111     MICROPY_FLOAT_CONST(1e-32), MICROPY_FLOAT_CONST(1e-16), MICROPY_FLOAT_CONST(1e-8), MICROPY_FLOAT_CONST(1e-4), MICROPY_FLOAT_CONST(1e-2), MICROPY_FLOAT_CONST(1e-1)
112 };
113 
mp_format_float(FPTYPE f,char * buf,size_t buf_size,char fmt,int prec,char sign)114 int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) {
115 
116     char *s = buf;
117 
118     if (buf_size <= FPMIN_BUF_SIZE) {
119         // FPMIN_BUF_SIZE is the minimum size needed to store any FP number.
120         // If the buffer does not have enough room for this (plus null terminator)
121         // then don't try to format the float.
122 
123         if (buf_size >= 2) {
124             *s++ = '?';
125         }
126         if (buf_size >= 1) {
127             *s = '\0';
128         }
129         return buf_size >= 2;
130     }
131     if (fp_signbit(f) && !fp_isnan(f)) {
132         *s++ = '-';
133         f = -f;
134     } else {
135         if (sign) {
136             *s++ = sign;
137         }
138     }
139 
140     // buf_remaining contains bytes available for digits and exponent.
141     // It is buf_size minus room for the sign and null byte.
142     int buf_remaining = buf_size - 1 - (s - buf);
143 
144     {
145         char uc = fmt & 0x20;
146         if (fp_isinf(f)) {
147             *s++ = 'I' ^ uc;
148             *s++ = 'N' ^ uc;
149             *s++ = 'F' ^ uc;
150             goto ret;
151         } else if (fp_isnan(f)) {
152             *s++ = 'N' ^ uc;
153             *s++ = 'A' ^ uc;
154             *s++ = 'N' ^ uc;
155         ret:
156             *s = '\0';
157             return s - buf;
158         }
159     }
160 
161     if (prec < 0) {
162         prec = 6;
163     }
164     char e_char = 'E' | (fmt & 0x20);   // e_char will match case of fmt
165     fmt |= 0x20; // Force fmt to be lowercase
166     char org_fmt = fmt;
167     if (fmt == 'g' && prec == 0) {
168         prec = 1;
169     }
170     int e, e1;
171     int dec = 0;
172     char e_sign = '\0';
173     int num_digits = 0;
174     const FPTYPE *pos_pow = g_pos_pow;
175     const FPTYPE *neg_pow = g_neg_pow;
176 
177     if (fp_iszero(f)) {
178         e = 0;
179         if (fmt == 'f') {
180             // Truncate precision to prevent buffer overflow
181             if (prec + 2 > buf_remaining) {
182                 prec = buf_remaining - 2;
183             }
184             num_digits = prec + 1;
185         } else {
186             // Truncate precision to prevent buffer overflow
187             if (prec + 6 > buf_remaining) {
188                 prec = buf_remaining - 6;
189             }
190             if (fmt == 'e') {
191                 e_sign = '+';
192             }
193         }
194     } else if (fp_isless1(f)) {
195         // We need to figure out what an integer digit will be used
196         // in case 'f' is used (or we revert other format to it below).
197         // As we just tested number to be <1, this is obviously 0,
198         // but we can round it up to 1 below.
199         char first_dig = '0';
200         if (f >= FPROUND_TO_ONE) {
201             first_dig = '1';
202         }
203 
204         // Build negative exponent
205         for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) {
206             if (*neg_pow > f) {
207                 e += e1;
208                 f *= *pos_pow;
209             }
210         }
211         char e_sign_char = '-';
212         if (fp_isless1(f) && f >= FPROUND_TO_ONE) {
213             f = FPCONST(1.0);
214             if (e == 0) {
215                 e_sign_char = '+';
216             }
217         } else if (fp_isless1(f)) {
218             e++;
219             f *= FPCONST(10.0);
220         }
221 
222         // If the user specified 'g' format, and e is <= 4, then we'll switch
223         // to the fixed format ('f')
224 
225         if (fmt == 'f' || (fmt == 'g' && e <= 4)) {
226             fmt = 'f';
227             dec = -1;
228             *s++ = first_dig;
229 
230             if (org_fmt == 'g') {
231                 prec += (e - 1);
232             }
233 
234             // truncate precision to prevent buffer overflow
235             if (prec + 2 > buf_remaining) {
236                 prec = buf_remaining - 2;
237             }
238 
239             num_digits = prec;
240             if (num_digits) {
241                 *s++ = '.';
242                 while (--e && num_digits) {
243                     *s++ = '0';
244                     num_digits--;
245                 }
246             }
247         } else {
248             // For e & g formats, we'll be printing the exponent, so set the
249             // sign.
250             e_sign = e_sign_char;
251             dec = 0;
252 
253             if (prec > (buf_remaining - FPMIN_BUF_SIZE)) {
254                 prec = buf_remaining - FPMIN_BUF_SIZE;
255                 if (fmt == 'g') {
256                     prec++;
257                 }
258             }
259         }
260     } else {
261         // Build positive exponent
262         for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) {
263             if (*pos_pow <= f) {
264                 e += e1;
265                 f *= *neg_pow;
266             }
267         }
268 
269         // It can be that f was right on the edge of an entry in pos_pow needs to be reduced
270         if ((int)f >= 10) {
271             e += 1;
272             f *= FPCONST(0.1);
273         }
274 
275         // If the user specified fixed format (fmt == 'f') and e makes the
276         // number too big to fit into the available buffer, then we'll
277         // switch to the 'e' format.
278 
279         if (fmt == 'f') {
280             if (e >= buf_remaining) {
281                 fmt = 'e';
282             } else if ((e + prec + 2) > buf_remaining) {
283                 prec = buf_remaining - e - 2;
284                 if (prec < 0) {
285                     // This means no decimal point, so we can add one back
286                     // for the decimal.
287                     prec++;
288                 }
289             }
290         }
291         if (fmt == 'e' && prec > (buf_remaining - FPMIN_BUF_SIZE)) {
292             prec = buf_remaining - FPMIN_BUF_SIZE;
293         }
294         if (fmt == 'g') {
295             // Truncate precision to prevent buffer overflow
296             if (prec + (FPMIN_BUF_SIZE - 1) > buf_remaining) {
297                 prec = buf_remaining - (FPMIN_BUF_SIZE - 1);
298             }
299         }
300         // If the user specified 'g' format, and e is < prec, then we'll switch
301         // to the fixed format.
302 
303         if (fmt == 'g' && e < prec) {
304             fmt = 'f';
305             prec -= (e + 1);
306         }
307         if (fmt == 'f') {
308             dec = e;
309             num_digits = prec + e + 1;
310         } else {
311             e_sign = '+';
312         }
313     }
314     if (prec < 0) {
315         // This can happen when the prec is trimmed to prevent buffer overflow
316         prec = 0;
317     }
318 
319     // We now have num.f as a floating point number between >= 1 and < 10
320     // (or equal to zero), and e contains the absolute value of the power of
321     // 10 exponent. and (dec + 1) == the number of dgits before the decimal.
322 
323     // For e, prec is # digits after the decimal
324     // For f, prec is # digits after the decimal
325     // For g, prec is the max number of significant digits
326     //
327     // For e & g there will be a single digit before the decimal
328     // for f there will be e digits before the decimal
329 
330     if (fmt == 'e') {
331         num_digits = prec + 1;
332     } else if (fmt == 'g') {
333         if (prec == 0) {
334             prec = 1;
335         }
336         num_digits = prec;
337     }
338 
339     // Print the digits of the mantissa
340     for (int i = 0; i < num_digits; ++i, --dec) {
341         int32_t d = (int32_t)f;
342         if (d < 0) {
343             *s++ = '0';
344         } else {
345             *s++ = '0' + d;
346         }
347         if (dec == 0 && prec > 0) {
348             *s++ = '.';
349         }
350         f -= (FPTYPE)d;
351         f *= FPCONST(10.0);
352     }
353 
354     // Round
355     // If we print non-exponential format (i.e. 'f'), but a digit we're going
356     // to round by (e) is too far away, then there's nothing to round.
357     if ((org_fmt != 'f' || e <= num_digits) && f >= FPCONST(5.0)) {
358         char *rs = s;
359         rs--;
360         while (1) {
361             if (*rs == '.') {
362                 rs--;
363                 continue;
364             }
365             if (*rs < '0' || *rs > '9') {
366                 // + or -
367                 rs++; // So we sit on the digit to the right of the sign
368                 break;
369             }
370             if (*rs < '9') {
371                 (*rs)++;
372                 break;
373             }
374             *rs = '0';
375             if (rs == buf) {
376                 break;
377             }
378             rs--;
379         }
380         if (*rs == '0') {
381             // We need to insert a 1
382             if (rs[1] == '.' && fmt != 'f') {
383                 // We're going to round 9.99 to 10.00
384                 // Move the decimal point
385                 rs[0] = '.';
386                 rs[1] = '0';
387                 if (e_sign == '-') {
388                     e--;
389                     if (e == 0) {
390                         e_sign = '+';
391                     }
392                 } else {
393                     e++;
394                 }
395             } else {
396                 // Need at extra digit at the end to make room for the leading '1'
397                 s++;
398             }
399             char *ss = s;
400             while (ss > rs) {
401                 *ss = ss[-1];
402                 ss--;
403             }
404             *rs = '1';
405         }
406     }
407 
408     // verify that we did not overrun the input buffer so far
409     assert((size_t)(s + 1 - buf) <= buf_size);
410 
411     if (org_fmt == 'g' && prec > 0) {
412         // Remove trailing zeros and a trailing decimal point
413         while (s[-1] == '0') {
414             s--;
415         }
416         if (s[-1] == '.') {
417             s--;
418         }
419     }
420     // Append the exponent
421     if (e_sign) {
422         *s++ = e_char;
423         *s++ = e_sign;
424         if (FPMIN_BUF_SIZE == 7 && e >= 100) {
425             *s++ = '0' + (e / 100);
426         }
427         *s++ = '0' + ((e / 10) % 10);
428         *s++ = '0' + (e % 10);
429     }
430     *s = '\0';
431 
432     // verify that we did not overrun the input buffer
433     assert((size_t)(s + 1 - buf) <= buf_size);
434 
435     return s - buf;
436 }
437 
438 #endif // MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE
439