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:
parent
e720bbdd76
commit
6e74fecb42
4 changed files with 27 additions and 68 deletions
|
|
@ -38,51 +38,39 @@ proc trailingZeros2Digits*(digits: uint32): int32 {.inline.} =
|
||||||
assert(digits <= 99)
|
assert(digits <= 99)
|
||||||
return trailingZeros100[digits]
|
return trailingZeros100[digits]
|
||||||
|
|
||||||
func digits10*(num: uint64): int {.noinline.} =
|
func addIntImpl*(result: var string, origin: uint64) =
|
||||||
if num < 10'u64:
|
var tmp {.noinit.}: array[24, char]
|
||||||
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 num = origin
|
||||||
var next = length - 1
|
var next = tmp.len - 1
|
||||||
const nbatch = 100
|
const nbatch = 100
|
||||||
|
|
||||||
while num >= nbatch:
|
while num >= nbatch:
|
||||||
let originNum = num
|
let originNum = num
|
||||||
num = num div nbatch
|
num = num div nbatch
|
||||||
let index = (originNum - num * nbatch) shl 1
|
let index = (originNum - num * nbatch) shl 1
|
||||||
result[next] = digits100[index + 1]
|
tmp[next] = digits100[index + 1]
|
||||||
result[next - 1] = digits100[index]
|
tmp[next - 1] = digits100[index]
|
||||||
dec(next, 2)
|
dec(next, 2)
|
||||||
|
|
||||||
# process last 1-2 digits
|
# process last 1-2 digits
|
||||||
if num < 10:
|
if num < 10:
|
||||||
result[next] = chr(ord('0') + num)
|
tmp[next] = chr(ord('0') + num)
|
||||||
else:
|
else:
|
||||||
let index = num * 2
|
let index = num * 2
|
||||||
result[next] = digits100[index + 1]
|
tmp[next] = digits100[index + 1]
|
||||||
result[next - 1] = digits100[index]
|
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:.
|
## spelling `toString`:idx:.
|
||||||
|
|
||||||
template dollarImpl(x: uint | uint64, result: var string) =
|
template dollarImpl(x: uint | uint64, result: var string) =
|
||||||
let length = digits10(x)
|
addIntImpl(result, x)
|
||||||
setLen(result, length)
|
|
||||||
numToString(result, x, length)
|
|
||||||
|
|
||||||
when defined(js):
|
when defined(js):
|
||||||
import std/private/since
|
import std/private/since
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,6 @@ proc addInt*(result: var string; x: int64) =
|
||||||
## a = "123"
|
## a = "123"
|
||||||
## b = 45
|
## b = 45
|
||||||
## a.addInt(b) # a <- "12345"
|
## a.addInt(b) # a <- "12345"
|
||||||
let base = result.len
|
|
||||||
var length: int
|
|
||||||
var num: uint64
|
var num: uint64
|
||||||
|
|
||||||
if x < 0:
|
if x < 0:
|
||||||
|
|
@ -60,14 +58,12 @@ proc addInt*(result: var string; x: int64) =
|
||||||
num = uint64(x)
|
num = uint64(x)
|
||||||
else:
|
else:
|
||||||
num = uint64(-x)
|
num = uint64(-x)
|
||||||
length = base + digits10(num) + 1
|
let base = result.len
|
||||||
setLen(result, length)
|
setLen(result, base + 1)
|
||||||
result[base] = '-'
|
result[base] = '-'
|
||||||
else:
|
else:
|
||||||
num = uint64(x)
|
num = uint64(x)
|
||||||
length = base + digits10(num)
|
addIntImpl(result, num)
|
||||||
setLen(result, length)
|
|
||||||
numToString(result, num, length)
|
|
||||||
|
|
||||||
proc nimIntToStr(x: int): string {.compilerRtl.} =
|
proc nimIntToStr(x: int): string {.compilerRtl.} =
|
||||||
result = newStringOfCap(sizeof(x)*4)
|
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()
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue