diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2019-09-20 10:41:40 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-20 10:41:40 +0200 |
commit | 7bc5bf83345a0ebaef3dca9395f0bc7d285ba61e (patch) | |
tree | 1a83ef297e0e78b0c3a29d7d87b035e168d242b9 /lib/system/formatfloat.nim | |
parent | 04c803d6df63bebd709a203c9055b21750c7927e (diff) | |
download | Nim-7bc5bf83345a0ebaef3dca9395f0bc7d285ba61e.tar.gz |
consistent floating point output (#12219)
* unify float printing * makes tests green
Diffstat (limited to 'lib/system/formatfloat.nim')
-rw-r--r-- | lib/system/formatfloat.nim | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/lib/system/formatfloat.nim b/lib/system/formatfloat.nim new file mode 100644 index 000000000..dbe9a4145 --- /dev/null +++ b/lib/system/formatfloat.nim @@ -0,0 +1,59 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2019 Nim contributors +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>", + importc: "sprintf", varargs, noSideEffect.} + +proc writeToBuffer(buf: var array[65, char]; value: cstring) = + var i = 0 + while value[i] != '\0': + buf[i] = value[i] + inc i + +proc writeFloatToBuffer*(buf: var array[65, char]; value: BiggestFloat): int = + ## This is the implementation to format floats in the Nim + ## programming language. The specific format for floating point + ## numbers is not specified in the Nim programming language and + ## might change slightly in the future, but at least wherever you + ## format a float, it should be consistent. + ## + ## returns the amount of bytes written to `buf` not counting the + ## terminating '\0' character. + ## + ## * `buf` - A buffer to write into. The buffer does not need to be + ## initialized and it will be overridden. + ## + var n: int = c_sprintf(addr buf, "%.16g", value) + var hasDot = false + for i in 0..n-1: + if buf[i] == ',': + buf[i] = '.' + hasDot = true + elif buf[i] in {'a'..'z', 'A'..'Z', '.'}: + hasDot = true + if not hasDot: + buf[n] = '.' + buf[n+1] = '0' + buf[n+2] = '\0' + result = n + 2 + else: + result = n + # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' + # of '-1.#IND' are produced. + # We want to get rid of these here: + if buf[n-1] in {'n', 'N', 'D', 'd'}: + writeToBuffer(buf, "nan") + result = 3 + elif buf[n-1] == 'F': + if buf[0] == '-': + writeToBuffer(buf, "-inf") + result = 4 + else: + writeToBuffer(buf, "inf") + result = 3 |