summary refs log tree commit diff stats
path: root/lib/system/formatfloat.nim
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2021-06-01 22:29:53 +0200
committerGitHub <noreply@github.com>2021-06-01 22:29:53 +0200
commit63db2b19bf0787db89ce89c8861e976d44e33cbd (patch)
tree5988de083bb7fd97f5f4a1d7da2526643b6ceaff /lib/system/formatfloat.nim
parentba3ec7b04954a9a60adb6e1a64405f7644f799ee (diff)
downloadNim-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.nim97
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