merge similar procs regarding digits (#18318)

This commit is contained in:
flywind
2021-06-22 23:02:32 +08:00
committed by GitHub
parent 037715285c
commit 9a81e91fa5
5 changed files with 105 additions and 133 deletions

View File

@@ -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]

View File

@@ -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
return "0"
elif x == 1:
return "1"
let half = i div 2
# Reverse
for t in 0 .. half-1: swap(result[t], result[i-t-1])
let length = digits10(x)
setLen(result, length)
numToString(result, x, length)
when defined(js):
import std/private/since

View File

@@ -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))

View File

@@ -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

View File

@@ -9,72 +9,9 @@
# 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
import std/private/digitsutils
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]
proc cmpStrings(a, b: string): int {.inline, compilerproc.} =
let alen = a.len
let blen = b.len