summary refs log tree commit diff stats
path: root/lib/std/private
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 /lib/std/private
parent037715285c088af46c94939f36abef63c95406e8 (diff)
downloadNim-9a81e91fa5d01cd6d60a408d0888dce4a9f49898.tar.gz
merge similar procs regarding digits (#18318)
Diffstat (limited to 'lib/std/private')
-rw-r--r--lib/std/private/digitsutils.nim88
1 files changed, 88 insertions, 0 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]