summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/std/private/digitsutils.nim58
-rw-r--r--lib/system/dollars.nim4
-rw-r--r--lib/system/strmantle.nim10
-rw-r--r--tests/stdlib/tdigitsutils.nim23
4 files changed, 27 insertions, 68 deletions
diff --git a/lib/std/private/digitsutils.nim b/lib/std/private/digitsutils.nim
index cc985c7bd..7aefc36bc 100644
--- a/lib/std/private/digitsutils.nim
+++ b/lib/std/private/digitsutils.nim
@@ -38,51 +38,39 @@ proc trailingZeros2Digits*(digits: uint32): int32 {.inline.} =
   assert(digits <= 99)
   return trailingZeros100[digits]
 
-func digits10*(num: uint64): int {.noinline.} =
-  if num < 10'u64:
-    result = 1
-  elif num < 100'u64:
-    result = 2
-  elif num < 1_000'u64:
-    result = 3
-  elif num < 10_000'u64:
-    result = 4
-  elif num < 100_000'u64:
-    result = 5
-  elif num < 1_000_000'u64:
-    result = 6
-  elif num < 10_000_000'u64:
-    result = 7
-  elif num < 100_000_000'u64:
-    result = 8
-  elif num < 1_000_000_000'u64:
-    result = 9
-  elif num < 10_000_000_000'u64:
-    result = 10
-  elif num < 100_000_000_000'u64:
-    result = 11
-  elif num < 1_000_000_000_000'u64:
-    result = 12
-  else:
-    result = 12 + digits10(num div 1_000_000_000_000'u64)
-
-template numToString*(result: var string, origin: uint64, length: int) =
+func addIntImpl*(result: var string, origin: uint64) =
+  var tmp {.noinit.}: array[24, char]
   var num = origin
-  var next = length - 1
+  var next = tmp.len - 1
   const nbatch = 100
 
   while num >= nbatch:
     let originNum = num
     num = num div nbatch
     let index = (originNum - num * nbatch) shl 1
-    result[next] = digits100[index + 1]
-    result[next - 1] = digits100[index]
+    tmp[next] = digits100[index + 1]
+    tmp[next - 1] = digits100[index]
     dec(next, 2)
 
   # process last 1-2 digits
   if num < 10:
-    result[next] = chr(ord('0') + num)
+    tmp[next] = chr(ord('0') + num)
   else:
     let index = num * 2
-    result[next] = digits100[index + 1]
-    result[next - 1] = digits100[index]
+    tmp[next] = digits100[index + 1]
+    tmp[next - 1] = digits100[index]
+    dec next
+  let n = result.len
+  let length = tmp.len - next
+  result.setLen n + length
+  when nimvm:
+    for i in 0..<length:
+      result[n+i] = tmp[next+i]
+  else:
+    when defined(js) or defined(nimscript):
+      for i in 0..<length:
+        result[n+i] = tmp[next+i]
+    else:
+      {.noSideEffect.}:
+        copyMem result[n].addr, tmp[next].addr, length
+
diff --git a/lib/system/dollars.nim b/lib/system/dollars.nim
index 3d824a965..c23ea347d 100644
--- a/lib/system/dollars.nim
+++ b/lib/system/dollars.nim
@@ -7,9 +7,7 @@ proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.}
   ## spelling `toString`:idx:.
 
 template dollarImpl(x: uint | uint64, result: var string) =
-  let length = digits10(x)
-  setLen(result, length)
-  numToString(result, x, length)
+  addIntImpl(result, x)
 
 when defined(js):
   import std/private/since
diff --git a/lib/system/strmantle.nim b/lib/system/strmantle.nim
index b60bc4b80..63e341763 100644
--- a/lib/system/strmantle.nim
+++ b/lib/system/strmantle.nim
@@ -51,8 +51,6 @@ proc addInt*(result: var string; x: int64) =
   ##     a = "123"
   ##     b = 45
   ##   a.addInt(b) # a <- "12345"
-  let base = result.len
-  var length: int
   var num: uint64
 
   if x < 0:
@@ -60,14 +58,12 @@ proc addInt*(result: var string; x: int64) =
       num = uint64(x)
     else:
       num = uint64(-x)
-    length = base + digits10(num) + 1
-    setLen(result, length)
+    let base = result.len
+    setLen(result, base + 1)
     result[base] = '-'
   else:
     num = uint64(x)
-    length = base + digits10(num)
-    setLen(result, length)
-  numToString(result, num, length)
+  addIntImpl(result, num)
 
 proc nimIntToStr(x: int): string {.compilerRtl.} =
   result = newStringOfCap(sizeof(x)*4)
diff --git a/tests/stdlib/tdigitsutils.nim b/tests/stdlib/tdigitsutils.nim
deleted file mode 100644
index 7cf63411f..000000000
--- a/tests/stdlib/tdigitsutils.nim
+++ /dev/null
@@ -1,23 +0,0 @@
-import std/private/digitsutils
-
-template main =
-  block: # digits10
-    doAssert digits10(0'u64) == 1
-    # checks correctness on all powers of 10 + [0,-1,1]
-    var x = 1'u64
-    var num = 1
-    while true:
-      # echo (x, num)
-      doAssert digits10(x) == num
-      doAssert digits10(x+1) == num
-      if x > 1:
-        doAssert digits10(x-1) == num - 1
-      num += 1
-      let xOld = x
-      x *= 10
-      if x < xOld:
-        # wrap-around
-        break
-
-static: main()
-main()