diff options
-rw-r--r-- | lib/std/private/digitsutils.nim | 58 | ||||
-rw-r--r-- | lib/system/dollars.nim | 4 | ||||
-rw-r--r-- | lib/system/strmantle.nim | 10 | ||||
-rw-r--r-- | tests/stdlib/tdigitsutils.nim | 23 |
4 files changed, 27 insertions, 68 deletions
diff --git a/lib/std/private/digitsutils.nim b/lib/std/private/digitsutils.nim index cc985c7bd..7aefc36bc 100644 --- a/lib/std/private/digitsutils.nim +++ b/lib/std/private/digitsutils.nim @@ -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 + diff --git a/lib/system/dollars.nim b/lib/system/dollars.nim index 3d824a965..c23ea347d 100644 --- a/lib/system/dollars.nim +++ b/lib/system/dollars.nim @@ -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 diff --git a/lib/system/strmantle.nim b/lib/system/strmantle.nim index b60bc4b80..63e341763 100644 --- a/lib/system/strmantle.nim +++ b/lib/system/strmantle.nim @@ -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) diff --git a/tests/stdlib/tdigitsutils.nim b/tests/stdlib/tdigitsutils.nim deleted file mode 100644 index 7cf63411f..000000000 --- a/tests/stdlib/tdigitsutils.nim +++ /dev/null @@ -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() |