summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorflywind <xzsflywind@gmail.com>2021-06-22 23:02:32 +0800
committerGitHub <noreply@github.com>2021-06-22 17:02:32 +0200
commit9a81e91fa5d01cd6d60a408d0888dce4a9f49898 (patch)
tree0c699301c696ec41583e344eefb3b2b755753bc0
parent037715285c088af46c94939f36abef63c95406e8 (diff)
downloadNim-9a81e91fa5d01cd6d60a408d0888dce4a9f49898.tar.gz
merge similar procs regarding digits (#18318)
-rw-r--r--lib/std/private/digitsutils.nim88
-rw-r--r--lib/system/dollars.nim25
-rw-r--r--lib/system/dragonbox.nim32
-rw-r--r--lib/system/schubfach.nim30
-rw-r--r--lib/system/strmantle.nim67
5 files changed, 107 insertions, 135 deletions
diff --git a/lib/std/private/digitsutils.nim b/lib/std/private/digitsutils.nim
new file mode 100644
index 000000000..cc985c7bd
--- /dev/null
+++ b/lib/std/private/digitsutils.nim
@@ -0,0 +1,88 @@
+const
+  trailingZeros100: array[100, int8] = [2'i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+    0, 0, 0, 0, 0, 0]
+
+  digits100: array[200, char] = ['0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5',
+    '0', '6', '0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
+    '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', '2', '2', '3',
+    '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '3', '0', '3', '1', '3', '2',
+    '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1',
+    '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0',
+    '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
+    '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8',
+    '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7',
+    '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6',
+    '8', '7', '8', '8', '8', '9', '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5',
+    '9', '6', '9', '7', '9', '8', '9', '9']
+
+# Inspired by https://engineering.fb.com/2013/03/15/developer-tools/three-optimization-tips-for-c
+# Generates:
+# .. code-block:: nim
+#   var res = ""
+#   for i in 0 .. 99:
+#     if i < 10:
+#       res.add "0" & $i
+#     else:
+#       res.add $i
+#   doAssert res == digits100
+
+proc utoa2Digits*(buf: var openArray[char]; pos: int; digits: uint32) {.inline.} =
+  assert(digits <= 99)
+  buf[pos] = digits100[2 * digits]
+  buf[pos+1] = digits100[2 * digits + 1]
+  #copyMem(buf, unsafeAddr(digits100[2 * digits]), 2 * sizeof((char)))
+
+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) =
+  var num = origin
+  var next = length - 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]
+    dec(next, 2)
+
+  # process last 1-2 digits
+  if num < 10:
+    result[next] = chr(ord('0') + num)
+  else:
+    let index = num * 2
+    result[next] = digits100[index + 1]
+    result[next - 1] = digits100[index]
diff --git a/lib/system/dollars.nim b/lib/system/dollars.nim
index 5a7a77e56..75390b0e1 100644
--- a/lib/system/dollars.nim
+++ b/lib/system/dollars.nim
@@ -1,3 +1,6 @@
+import std/private/digitsutils
+
+
 proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.}
   ## The stringify operator for an integer argument. Returns `x`
   ## converted to a decimal string. `$` is Nim's general way of
@@ -6,22 +9,14 @@ proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.}
 template dollarImpl(x: uint | uint64, result: var string) =
   type destTyp = typeof(x)
   if x == 0:
-    result = "0"
-  else:
-    result = newString(60)
-    var i = 0
-    var n = x
-    while n != 0:
-      let nn = n div destTyp(10)
-      result[i] = char(n - destTyp(10) * nn + ord('0'))
-      inc i
-      n = nn
-    result.setLen i
-
-    let half = i div 2
-    # Reverse
-    for t in 0 .. half-1: swap(result[t], result[i-t-1])
+    return "0"
+  elif x == 1:
+    return "1"
+
+  let length = digits10(x)
+  setLen(result, length)
 
+  numToString(result, x, length)
 
 when defined(js):
   import std/private/since
diff --git a/lib/system/dragonbox.nim b/lib/system/dragonbox.nim
index eec8749da..336c982c1 100644
--- a/lib/system/dragonbox.nim
+++ b/lib/system/dragonbox.nim
@@ -21,6 +21,10 @@
 ##  Note:
 ##  This function may temporarily write up to DtoaMinBufferLength characters into the buffer.
 
+
+import std/private/digitsutils
+
+
 const
   dtoaMinBufferLength*: cint = 64
 
@@ -1038,34 +1042,6 @@ proc toDecimal64*(ieeeSignificand: uint64; ieeeExponent: uint64): FloatingDecima
 ##  ToChars
 ## ==================================================================================================
 
-proc utoa2Digits*(buf: var openArray[char]; pos: int; digits: uint32) {.inline.} =
-  const
-    digits100: array[200, char] = ['0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5',
-      '0', '6', '0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
-      '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', '2', '2', '3',
-      '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '3', '0', '3', '1', '3', '2',
-      '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1',
-      '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0',
-      '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
-      '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8',
-      '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7',
-      '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6',
-      '8', '7', '8', '8', '8', '9', '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5',
-      '9', '6', '9', '7', '9', '8', '9', '9']
-  dragonbox_Assert(digits <= 99)
-  buf[pos] = digits100[2 * digits]
-  buf[pos+1] = digits100[2 * digits + 1]
-  #copyMem(buf, unsafeAddr(digits100[2 * digits]), 2 * sizeof((char)))
-
-proc trailingZeros2Digits*(digits: uint32): int32 {.inline.} =
-  const
-    trailingZeros100: array[100, int8] = [2'i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-      1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
-      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
-      0, 0, 0, 0, 0, 0]
-  dragonbox_Assert(digits <= 99)
-  return trailingZeros100[digits]
-
 when false:
   template `+!`(x: cstring; offset: int): cstring = cast[cstring](cast[uint](x) + uint(offset))
 
diff --git a/lib/system/schubfach.nim b/lib/system/schubfach.nim
index 94d3d3c25..5f974a79e 100644
--- a/lib/system/schubfach.nim
+++ b/lib/system/schubfach.nim
@@ -10,6 +10,9 @@
 ##      https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN
 ## --------------------------------------------------------------------------------------------------
 
+import std/private/digitsutils
+
+
 template sf_Assert(x: untyped): untyped =
   assert(x)
 
@@ -233,33 +236,6 @@ proc toDecimal32(ieeeSignificand: uint32; ieeeExponent: uint32): FloatingDecimal
 ##  ToChars
 ## ==================================================================================================
 
-proc utoa2Digits(buf: var openArray[char]; pos: int; digits: uint32) {.inline.} =
-  const
-    digits100: array[200, char] = ['0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5',
-      '0', '6', '0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
-      '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', '2', '2', '3',
-      '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '3', '0', '3', '1', '3', '2',
-      '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1',
-      '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0',
-      '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
-      '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8',
-      '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7',
-      '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6',
-      '8', '7', '8', '8', '8', '9', '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5',
-      '9', '6', '9', '7', '9', '8', '9', '9']
-  sf_Assert(digits <= 99)
-  buf[pos] = digits100[2 * digits]
-  buf[pos+1] = digits100[2 * digits + 1]
-
-proc trailingZeros2Digits(digits: uint32): int32 {.inline.} =
-  const
-    trailingZeros100: array[100, int8] = [2'i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-      1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
-      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
-      0, 0, 0, 0, 0, 0]
-  sf_Assert(digits <= 99)
-  return trailingZeros100[digits]
-
 proc printDecimalDigitsBackwards(buf: var openArray[char]; pos: int; output: uint32): int32 {.inline.} =
   var output = output
   var pos = pos
diff --git a/lib/system/strmantle.nim b/lib/system/strmantle.nim
index 1a32a4afe..b60bc4b80 100644
--- a/lib/system/strmantle.nim
+++ b/lib/system/strmantle.nim
@@ -9,71 +9,8 @@
 
 # Compilerprocs for strings that do not depend on the string implementation.
 
-const digitsTable = "0001020304050607080910111213141516171819" &
-    "2021222324252627282930313233343536373839" &
-    "4041424344454647484950515253545556575859" &
-    "6061626364656667686970717273747576777879" &
-    "8081828384858687888990919293949596979899"
-  # Inspired by https://engineering.fb.com/2013/03/15/developer-tools/three-optimization-tips-for-c
-  # Generates:
-  # .. code-block:: nim
-  #   var res = ""
-  #   for i in 0 .. 99:
-  #     if i < 10:
-  #       res.add "0" & $i
-  #     else:
-  #       res.add $i
-  #   doAssert res == digitsTable
-
-
-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) =
-  var num = origin
-  var next = length - 1
-  const nbatch = 100
-
-  while num >= nbatch:
-    let originNum = num
-    num = num div nbatch
-    let index = (originNum - num * nbatch) shl 1
-    result[next] = digitsTable[index + 1]
-    result[next - 1] = digitsTable[index]
-    dec(next, 2)
-
-  # process last 1-2 digits
-  if num < 10:
-    result[next] = chr(ord('0') + num)
-  else:
-    let index = num * 2
-    result[next] = digitsTable[index + 1]
-    result[next - 1] = digitsTable[index]
+import std/private/digitsutils
+
 
 proc cmpStrings(a, b: string): int {.inline, compilerproc.} =
   let alen = a.len