diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2021-06-01 22:29:53 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-01 22:29:53 +0200 |
commit | 63db2b19bf0787db89ce89c8861e976d44e33cbd (patch) | |
tree | 5988de083bb7fd97f5f4a1d7da2526643b6ceaff /lib/system/formatfloat.nim | |
parent | ba3ec7b04954a9a60adb6e1a64405f7644f799ee (diff) | |
download | Nim-63db2b19bf0787db89ce89c8861e976d44e33cbd.tar.gz |
use dragonbox algorithm; alternative to #18008 (#18139)
* use dragonbox algorithm; alternative to #18008 * removed unsafe code
Diffstat (limited to 'lib/system/formatfloat.nim')
-rw-r--r-- | lib/system/formatfloat.nim | 97 |
1 files changed, 51 insertions, 46 deletions
diff --git a/lib/system/formatfloat.nim b/lib/system/formatfloat.nim index cb46c8c36..41bc56adc 100644 --- a/lib/system/formatfloat.nim +++ b/lib/system/formatfloat.nim @@ -7,53 +7,58 @@ # distribution, for details about the copyright. # -proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>", - importc: "sprintf", varargs, noSideEffect.} +when not defined(nimLegacyAddFloat) and not defined(nimscript) and + not defined(js) and defined(nimHasDragonBox): + import dragonbox -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. + ## + ## returns the amount of bytes written to `buf` not counting the + ## terminating '\0' character. + result = toChars(buf, value, forceTrailingDotZero=true) + buf[result] = '\0' -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' or 'nan(ind)' - # 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: + 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. + ## + ## returns the amount of bytes written to `buf` not counting the + ## terminating '\0' character. + 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: - writeToBuffer(buf, "inf") + result = n + # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' or 'nan(ind)' + # 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 |