mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-19 23:41:29 +00:00
better addInt (#16160)
* better addint * Update lib/system/strmantle.nim Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
This commit is contained in:
@@ -9,6 +9,72 @@
|
||||
|
||||
# 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:
|
||||
result = 1
|
||||
elif num < 100:
|
||||
result = 2
|
||||
elif num < 1_000:
|
||||
result = 3
|
||||
elif num < 10_000:
|
||||
result = 4
|
||||
elif num < 100_000:
|
||||
result = 5
|
||||
elif num < 1_000_000:
|
||||
result = 6
|
||||
elif num < 10_000_000:
|
||||
result = 7
|
||||
elif num < 100_000_000:
|
||||
result = 8
|
||||
elif num < 1_000_000_000:
|
||||
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
|
||||
@@ -49,22 +115,22 @@ proc addInt*(result: var string; x: int64) =
|
||||
## b = 45
|
||||
## a.addInt(b) # a <- "12345"
|
||||
let base = result.len
|
||||
setLen(result, base + sizeof(x)*4)
|
||||
var i = 0
|
||||
var y = x
|
||||
while true:
|
||||
var d = y div 10
|
||||
result[base+i] = chr(abs(int(y - d*10)) + ord('0'))
|
||||
inc(i)
|
||||
y = d
|
||||
if y == 0: break
|
||||
var length: int
|
||||
var num: uint64
|
||||
|
||||
if x < 0:
|
||||
result[base+i] = '-'
|
||||
inc(i)
|
||||
setLen(result, base+i)
|
||||
# mirror the string:
|
||||
for j in 0..i div 2 - 1:
|
||||
swap(result[base+j], result[base+i-j-1])
|
||||
if x == low(int64):
|
||||
num = uint64(x)
|
||||
else:
|
||||
num = uint64(-x)
|
||||
length = base + digits10(num) + 1
|
||||
setLen(result, length)
|
||||
result[base] = '-'
|
||||
else:
|
||||
num = uint64(x)
|
||||
length = base + digits10(num)
|
||||
setLen(result, length)
|
||||
numToString(result, num, length)
|
||||
|
||||
proc nimIntToStr(x: int): string {.compilerRtl.} =
|
||||
result = newStringOfCap(sizeof(x)*4)
|
||||
|
||||
46
tests/system/tstrmantle.nim
Normal file
46
tests/system/tstrmantle.nim
Normal file
@@ -0,0 +1,46 @@
|
||||
var res = newStringOfCap(24)
|
||||
|
||||
for i in 0 .. 9:
|
||||
res.addInt int64(i)
|
||||
|
||||
doAssert res == "0123456789"
|
||||
|
||||
res = newStringOfCap(24)
|
||||
|
||||
for i in -9 .. 0:
|
||||
res.addInt int64(i)
|
||||
|
||||
doAssert res == "-9-8-7-6-5-4-3-2-10"
|
||||
|
||||
res = newStringOfCap(24)
|
||||
res.addInt high(int64)
|
||||
doAssert res == "9223372036854775807"
|
||||
|
||||
res = newStringOfCap(24)
|
||||
res.addInt low(int64)
|
||||
doAssert res == "-9223372036854775808"
|
||||
|
||||
res = newStringOfCap(12)
|
||||
res.addInt high(int32)
|
||||
doAssert res == "2147483647"
|
||||
|
||||
res = newStringOfCap(12)
|
||||
res.addInt low(int32)
|
||||
doAssert res == "-2147483648"
|
||||
|
||||
res = newStringOfCap(12)
|
||||
res.addInt high(int16)
|
||||
doAssert res == "32767"
|
||||
|
||||
res = newStringOfCap(212)
|
||||
res.addInt low(int16)
|
||||
doAssert res == "-32768"
|
||||
|
||||
|
||||
res = newStringOfCap(12)
|
||||
res.addInt high(int8)
|
||||
doAssert res == "127"
|
||||
|
||||
res = newStringOfCap(12)
|
||||
res.addInt low(int8)
|
||||
doAssert res == "-128"
|
||||
Reference in New Issue
Block a user