Division/modulo 2x faster by removing shift in MpUint bit_length

This commit is contained in:
mratsim 2018-02-17 00:47:17 +01:00
parent 1c5da77a29
commit 43cb3441bc
2 changed files with 39 additions and 14 deletions

View File

@ -11,10 +11,10 @@ macro getSubType*(T: typedesc): untyped =
proc bit_length*[T: SomeUnsignedInt](n: T): int {.noSideEffect.}= proc bit_length*[T: SomeUnsignedInt](n: T): int {.noSideEffect.}=
## Calculates how many bits are necessary to represent the number ## Calculates how many bits are necessary to represent the number
result = 1
var y: T = n shr 1 var n = n
while y != 0.T: while n != 0.T:
y = y shr 1 n = n shr 1
inc(result) inc(result)
proc bit_length*[T: Natural](n: T): int {.noSideEffect.}= proc bit_length*[T: Natural](n: T): int {.noSideEffect.}=
@ -22,20 +22,21 @@ proc bit_length*[T: Natural](n: T): int {.noSideEffect.}=
# #
# For some reason using "SomeUnsignedInt or Natural" directly makes Nim compiler # For some reason using "SomeUnsignedInt or Natural" directly makes Nim compiler
# throw a type mismatch # throw a type mismatch
result = 1
var y: T = n shr 1 var n = n
while y != 0.T: while n != 0.T:
y = y shr 1 n = n shr 1
inc(result) inc(result)
proc bit_length*[T: MpUint](n: T): int {.noSideEffect.}= proc bit_length*[T: MpUint](n: T): int {.noSideEffect.}=
## Calculates how many bits are necessary to represent the number ## Calculates how many bits are necessary to represent the number
const zero = T()
result = 1 const maxHalfRepr = n.lo.type.sizeof * 8 - 1
var y: T = n shr 1
while y != zero: if n.hi.bit_length == 0:
y = y shr 1 # TODO: shr is slow! n.lo.bit_length
inc(result) else:
n.hi.bit_length + maxHalfRepr
proc asUint*[T: MpUInt](n: T): auto {.noSideEffect, inline.}= proc asUint*[T: MpUInt](n: T): auto {.noSideEffect, inline.}=
## Casts a multiprecision integer to an uint of the same size ## Casts a multiprecision integer to an uint of the same size

24
src/uint_logical_ops.nim Normal file
View File

@ -0,0 +1,24 @@
# Copyright (c) 2018 Status Research & Development GmbH
# Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
import uint_type
proc `not`*(x: MpUint): MpUint {.noInit, noSideEffect, inline.}=
## Bitwise complement of unsigned integer x
result.lo = not x.lo
result.hi = not x.hi
proc `or`*(x, y: MpUint): MpUint {.noInit, noSideEffect, inline.}=
## `Bitwise or` of numbers x and y
result.lo = x.lo or y.lo
result.hi = x.hi or y.hi
proc `and`*(x, y: MpUint): MpUint {.noInit, noSideEffect, inline.}=
## `Bitwise and` of numbers x and y
result.lo = x.lo and y.lo
result.hi = x.hi and y.hi
proc `xor`*(x, y: MpUint): MpUint {.noInit, noSideEffect, inline.}=
## `Bitwise xor` of numbers x and y
result.lo = x.lo xor y.lo
result.hi = x.hi xor y.hi