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
67union floatbits {
68 float f;
69 uint32_t u;
70};
71static 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)
77static inline int fp_iszero(float x) {
78 union floatbits fb = {x};
79 return fb.u == 0;
80}
81static 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
101static 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};
107static 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
114int 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