summaryrefslogtreecommitdiffstatshomepage
path: root/py/format-float.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-03-10 13:27:02 +0000
committerDamien George <damien.p.george@gmail.com>2014-03-10 13:27:02 +0000
commit8bfec2b53822e2b62c4577b32e0beae398a16297 (patch)
tree3116ca2b8fdad7c1d3b1221d658f9eea7a6575a3 /py/format-float.c
parent0a8458c353b60420f17050d819912df9b168d0cb (diff)
downloadmicropython-8bfec2b53822e2b62c4577b32e0beae398a16297.tar.gz
micropython-8bfec2b53822e2b62c4577b32e0beae398a16297.zip
Rename formatfloat file; remove MICROPY_ENABLE_FLOAT from mpconfigport.h.
MICROPY_ENABLE_FLOAT is automatically set in mpconfig.h if MICROPY_FLOAT_IMPL is set to a non-zero value.
Diffstat (limited to 'py/format-float.c')
-rw-r--r--py/format-float.c311
1 files changed, 0 insertions, 311 deletions
diff --git a/py/format-float.c b/py/format-float.c
deleted file mode 100644
index 5411ae24f6..0000000000
--- a/py/format-float.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/***********************************************************************
-
- format-float.c - Ruutine for converting a single-precision floating
- point number into a string.
-
- The code in this funcion was inspired from Fred Bayer's pdouble.c.
- Since pdouble.c was released as Public Domain, I'm releasing this
- code as public domain as well.
-
- The original code can be found in https://github.com/dhylands/format-float
-
- Dave Hylands
-
-***********************************************************************/
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "mpconfig.h"
-
-#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
-#include "format-float.h"
-
-// 1 sign bit, 8 exponent bits, and 23 mantissa bits.
-// exponent values 0 and 255 are reserved, exponent can be 1 to 254.
-// exponent is stored with a bias of 127.
-// The min and max floats are on the order of 1x10^37 and 1x10^-37
-
-#define FLT_SIGN_MASK 0x80000000
-#define FLT_EXP_MASK 0x7F800000
-#define FLT_MAN_MASK 0x007FFFFF
-
-static const float g_pos_pow[] = {
- 1e32, 1e16, 1e8, 1e4, 1e2, 1e1
-};
-static const float g_neg_pow[] = {
- 1e-32, 1e-16, 1e-8, 1e-4, 1e-2, 1e-1
-};
-
-int format_float(float f, char *buf, size_t buf_size, char fmt, int prec, char sign) {
-
- char *s = buf;
- int buf_remaining = buf_size - 1;
-
- union {
- float f;
- uint32_t u;
- } num = {f};
-
- if (buf_size < 7) {
- // Smallest exp notion is -9e+99 which is 6 chars plus terminating
- // nulll.
-
- if (buf_size >= 2) {
- *s++ = '?';
- }
- if (buf_size >= 1) {
- *s++ = '\0';
- }
- return buf_size >= 2;
- }
- if (num.u & FLT_SIGN_MASK) {
- *s++ = '-';
- num.u &= ~FLT_SIGN_MASK;
- } else {
- if (sign) {
- *s++ = sign;
- }
- }
- buf_remaining -= (s - buf); // Adjust for sign
-
- if ((num.u & FLT_EXP_MASK) == FLT_EXP_MASK) {
- char uc = fmt & 0x20;
- if ((num.u & FLT_MAN_MASK) == 0) {
- *s++ = 'I' ^ uc;
- *s++ = 'N' ^ uc;
- *s++ = 'F' ^ uc;
- } else {
- *s++ = 'N' ^ uc;
- *s++ = 'A' ^ uc;
- *s++ = 'N' ^ uc;
- }
- *s = '\0';
- return s - buf;
- }
-
- if (prec < 0) {
- prec = 6;
- }
- char e_char = 'E' | (fmt & 0x20); // e_char will match case of fmt
- fmt |= 0x20; // Force fmt to be lowercase
- char org_fmt = fmt;
- if (fmt == 'g' && prec == 0) {
- prec = 1;
- }
- int e, e1;
- int dec = 0;
- char e_sign = '\0';
- int num_digits = 0;
- const float *pos_pow = g_pos_pow;
- const float *neg_pow = g_neg_pow;
-
- if (num.u == 0) {
- e = 0;
- if (fmt == 'e') {
- e_sign = '+';
- } else if (fmt == 'f') {
- num_digits = prec + 1;
- }
- } else if (num.u < 0x3f800000) { // f < 1.0
- // Build negative exponent
- for (e = 0, e1 = 32; e1; e1 >>= 1, pos_pow++, neg_pow++) {
- if (*neg_pow > num.f) {
- e += e1;
- num.f *= *pos_pow;
- }
- }
- if (num.f < 1.0F && num.f >= 0.9999995F) {
- num.f = 1.0F;
- } else {
- e++;
- num.f *= 10.0F;
- }
-
- // If the user specified 'g' format, and e is <= 4, then we'll switch
- // to the fixed format ('f')
-
- if (fmt == 'f' || (fmt == 'g' && e <= 4)) {
- fmt = 'f';
- dec = -1;
- *s++ = '0';
-
- if (prec + e + 1 > buf_remaining) {
- prec = buf_remaining - e - 1;
- }
-
- if (org_fmt == 'g') {
- prec += (e - 1);
- }
- num_digits = prec;
- if (num_digits) {
- *s++ = '.';
- while (--e && num_digits) {
- *s++ = '0';
- num_digits--;
- }
- }
- } else {
- // For e & g formats, we'll be printing the exponent, so set the
- // sign.
- e_sign = '-';
- dec = 0;
-
- if (prec > (buf_remaining - 6)) {
- prec = buf_remaining - 6;
- if (fmt == 'g') {
- prec++;
- }
- }
- }
- } else {
- // Build positive exponent
- for (e = 0, e1 = 32; e1; e1 >>= 1, pos_pow++, neg_pow++) {
- if (*pos_pow <= num.f) {
- e += e1;
- num.f *= *neg_pow;
- }
- }
-
- // If the user specified fixed format (fmt == 'f') and e makes the
- // number too big to fit into the available buffer, then we'll
- // switch to the 'e' format.
-
- if (fmt == 'f') {
- if (e >= buf_remaining) {
- fmt = 'e';
- } else if ((e + prec + 2) > buf_remaining) {
- prec = buf_remaining - e - 2;
- if (prec < 0) {
- // This means no decimal point, so we can add one back
- // for the decimal.
- prec++;
- }
- }
- }
- if (fmt == 'e' && prec > (buf_remaining - 6)) {
- prec = buf_remaining - 6;
- }
- // If the user specified 'g' format, and e is < prec, then we'll switch
- // to the fixed format.
-
- if (fmt == 'g' && e < prec) {
- fmt = 'f';
- prec -= (e + 1);
- }
- if (fmt == 'f') {
- dec = e;
- num_digits = prec + e + 1;
- } else {
- e_sign = '+';
- }
- }
- if (prec < 0) {
- // This can happen when the prec is trimmed to prevent buffer overflow
- prec = 0;
- }
-
- // We now have num.f as a floating point number between >= 1 and < 10
- // (or equal to zero), and e contains the absolute value of the power of
- // 10 exponent. and (dec + 1) == the number of dgits before the decimal.
-
- // For e, prec is # digits after the decimal
- // For f, prec is # digits after the decimal
- // For g, prec is the max number of significant digits
- //
- // For e & g there will be a single digit before the decimal
- // for f there will be e digits before the decimal
-
- if (fmt == 'e') {
- num_digits = prec + 1;
- } else if (fmt == 'g') {
- if (prec == 0) {
- prec = 1;
- }
- num_digits = prec;
- }
-
- // Print the digits of the mantissa
- for (int i = 0; i < num_digits; ++i, --dec) {
- int32_t d = num.f;
- *s++ = '0' + d;
- if (dec == 0 && prec > 0) {
- *s++ = '.';
- }
- num.f -= (float)d;
- num.f *= 10.0F;
- }
-
- // Round
- if (num.f >= 5.0F) {
- char *rs = s;
- rs--;
- while (1) {
- if (*rs == '.') {
- rs--;
- continue;
- }
- if (*rs < '0' || *rs > '9') {
- // + or -
- rs++; // So we sit on the digit to the right of the sign
- break;
- }
- if (*rs < '9') {
- (*rs)++;
- break;
- }
- *rs = '0';
- if (rs == buf) {
- break;
- }
- rs--;
- }
- if (*rs == '0') {
- // We need to insert a 1
- if (rs[1] == '.' && fmt != 'f') {
- // We're going to round 9.99 to 10.00
- // Move the decimal point
- rs[0] = '.';
- rs[1] = '0';
- if (e_sign == '-') {
- e--;
- } else {
- e++;
- }
- }
- s++;
- char *ss = s;
- while (ss > rs) {
- *ss = ss[-1];
- ss--;
- }
- *rs = '1';
- }
- if (num.u < 0x3f800000 && fmt == 'f') {
- // We rounded up to 1.0
- prec--;
- }
- }
-
- if (org_fmt == 'g' && prec > 0) {
- // Remove trailing zeros and a trailing decimal point
- while (s[-1] == '0') {
- s--;
- }
- if (s[-1] == '.') {
- s--;
- }
- }
- // Append the exponent
- if (e_sign) {
- *s++ = e_char;
- *s++ = e_sign;
- *s++ = '0' + (e / 10);
- *s++ = '0' + (e % 10);
- }
- *s = '\0';
-
- return s - buf;
-}
-
-#endif