mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-04 10:54:42 +00:00
Simplify addInt, remove digits10 (#18356)
* Simplify addInt, remove digits10 Co-authored-by: Charles Blake <charlechaud@gmail.com> * Fix bootstrapping * Add noInit to tmp array * noInit -> noinit Co-authored-by: Charles Blake <charlechaud@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user