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