Skip to content

Instantly share code, notes, and snippets.

@mratsim
Created September 28, 2018 17:07
Show Gist options
  • Save mratsim/f822885269cbcf315082fafa71bdf16c to your computer and use it in GitHub Desktop.
Save mratsim/f822885269cbcf315082fafa71bdf16c to your computer and use it in GitHub Desktop.
Constant time bit setter for nim-bn-curve
var a: array[2, uint64]
func toBinString*[N: static int](x: array[N, uint64]): string =
const binChar = ['0', '1']
const byte_size = N*8
let bytes = cast[ptr array[byte_size, byte]](x.unsafeaddr)
result = newStringOfCap(byte_size*8)
for i in 0 ..< byte_size:
# We assume a little-endian arch
if i mod 8 == 0:
result.add '_'
let curr = bytes[bytes[].high - i]
result.add binChar[(curr and 0b10000000) shr 7]
result.add binChar[(curr and 0b01000000) shr 6]
result.add binChar[(curr and 0b00100000) shr 5]
result.add binChar[(curr and 0b00010000) shr 4]
result.add binChar[(curr and 0b00001000) shr 3]
result.add binChar[(curr and 0b00000100) shr 2]
result.add binChar[(curr and 0b00000010) shr 1]
result.add binChar[(curr and 0b00000001) ]
a[0] = 1'u64
a[1] = 15'u64
echo a.toBinString
echo "########"
type
BNU256* = array[4, uint64]
BNU512* = array[8, uint64]
func setBitAlt1(a: var BNU256, n: int, to: bool): bool {.inline.}=
if n >= 256:
return
let
index = n and 63
part = n shr 6
value = to.uint64
a[part] = a[part] and not(1'u64 shl index) or (value shl index)
result = true
template `-`(x: uint64): uint64 = x.not + 1
func setBitAlt2(a: var BNU256, n: int, to: bool): bool {.inline.}=
if n >= 256:
return
let
index = n and 63
part = n shr 6
value = to.uint64
a[part] = a[part] xor ((-value xor a[part]) and (1'u64 shl index))
result = true
var b: BNU256
discard b.setBitAlt1(3, true)
echo b.toBinString
discard b.setBitAlt1(3, false)
echo b.toBinString
discard b.setBitAlt2(3, true)
echo b.toBinString
discard b.setBitAlt2(3, false)
echo b.toBinString
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment