summaryrefslogtreecommitdiff
path: root/py/formatfloat.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/formatfloat.c')
-rw-r--r--py/formatfloat.c90
1 files changed, 79 insertions, 11 deletions
diff --git a/py/formatfloat.c b/py/formatfloat.c
index 64f013147..cc0636100 100644
--- a/py/formatfloat.c
+++ b/py/formatfloat.c
@@ -24,10 +24,15 @@
* THE SOFTWARE.
*/
+#include <stdlib.h>
+#include <stdint.h>
+#include "py/formatfloat.h"
+
+#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
/***********************************************************************
- formatfloat.c - Ruutine for converting a single-precision floating
- point number into a string.
+ Routine 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
@@ -39,15 +44,6 @@
***********************************************************************/
-#include <stdlib.h>
-#include <stdint.h>
-
-#include "py/mpconfig.h"
-
-#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
-
-#include "py/formatfloat.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.
@@ -341,4 +337,76 @@ int mp_format_float(float f, char *buf, size_t buf_size, char fmt, int prec, cha
return s - buf;
}
+#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
+
+#include <errno.h>
+#include <stdio.h>
+
+#ifdef _MSC_VER
+// For msvc we need to address some quirks in the snprintf implementation:
+// - there is no standard snprintf, it is named _snprintf instead
+// - 'F' format isn't handled so use 'f'
+// - nan and inf are printed as 1.#QNAN and 1.#INF
+#include <math.h>
+#include <string.h>
+
+STATIC int copy_with_sign(char *dest, size_t bufSize, const char *value, char sign) {
+ if (bufSize == 0) {
+ return 0;
+ }
+ size_t numSignChars = 0;
+ if (sign) {
+ *dest = sign;
+ ++numSignChars;
+ }
+ // check total length including terminator
+ size_t length = strlen(value) + 1 + numSignChars;
+ if (length > bufSize) {
+ length = bufSize;
+ }
+ // length without terminator
+ --length;
+ if (length > numSignChars) {
+ memcpy(dest + numSignChars, value, length - numSignChars);
+ }
+ dest[length] = 0;
+ return length;
+}
+
+#define snprintf _snprintf
+#endif
+
+int mp_format_float(double value, char *buf, size_t bufSize, char fmt, int prec, char sign) {
+ if (!buf) {
+ errno = EINVAL;
+ return -1;
+ }
+#ifdef _MSC_VER
+ if (isnan(value)) {
+ return copy_with_sign(buf, bufSize, "nan", sign);
+ } else if (isinf(value)) {
+ return copy_with_sign(buf, bufSize, "inf", value > 0.0 ? sign : '-');
+ } else {
+ if (fmt == 'F') {
+ fmt = 'f';
+ }
+#endif
+ char fmt_buf[6];
+ char *fmt_s = fmt_buf;
+
+ *fmt_s++ = '%';
+ if (sign) {
+ *fmt_s++ = sign;
+ }
+ *fmt_s++ = '.';
+ *fmt_s++ = '*';
+ *fmt_s++ = fmt;
+ *fmt_s = '\0';
+
+ return snprintf(buf, bufSize, fmt_buf, prec, value);
+#ifdef _MSC_VER
+ }
+#endif
+}
+
#endif