2018-04-25 21:21:25 +02:00
|
|
|
# Stint
|
2018-03-02 11:48:08 +01:00
|
|
|
# Copyright 2018 Status Research & Development GmbH
|
|
|
|
# Licensed under either of
|
|
|
|
#
|
|
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
|
|
|
#
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
2018-05-06 22:29:08 +02:00
|
|
|
|
2020-06-12 19:23:03 +02:00
|
|
|
import ./datatypes
|
2018-02-16 11:33:11 +01:00
|
|
|
|
2020-06-12 19:59:03 +02:00
|
|
|
{.push raises: [], inline, noInit, gcsafe.}
|
|
|
|
|
|
|
|
func `not`*(x: Limbs): Limbs =
|
2018-02-16 11:33:11 +01:00
|
|
|
## Bitwise complement of unsigned integer x
|
2020-06-12 19:23:03 +02:00
|
|
|
for wr, wx in leastToMostSig(result, x):
|
|
|
|
wr = not wx
|
2018-02-16 11:33:11 +01:00
|
|
|
|
2020-06-12 19:59:03 +02:00
|
|
|
func `or`*(x, y: Limbs): Limbs =
|
2018-02-16 11:33:11 +01:00
|
|
|
## `Bitwise or` of numbers x and y
|
2020-06-12 19:23:03 +02:00
|
|
|
for wr, wx, wy in leastToMostSig(result, x, y):
|
|
|
|
wr = wx or wy
|
2018-02-16 11:33:11 +01:00
|
|
|
|
2020-06-12 19:59:03 +02:00
|
|
|
func `and`*(x, y: Limbs): Limbs =
|
2018-02-16 11:33:11 +01:00
|
|
|
## `Bitwise and` of numbers x and y
|
2020-06-12 19:23:03 +02:00
|
|
|
for wr, wx, wy in leastToMostSig(result, x, y):
|
|
|
|
wr = wx and wy
|
2018-02-16 11:33:11 +01:00
|
|
|
|
2020-06-12 19:59:03 +02:00
|
|
|
func `xor`*(x, y: Limbs): Limbs =
|
2018-02-16 11:33:11 +01:00
|
|
|
## `Bitwise xor` of numbers x and y
|
2020-06-12 19:23:03 +02:00
|
|
|
for wr, wx, wy in leastToMostSig(result, x, y):
|
|
|
|
wr = wx xor wy
|
|
|
|
|
2020-06-12 19:59:03 +02:00
|
|
|
func `shr`*(x: Limbs, k: SomeInteger): Limbs =
|
2020-06-12 19:23:03 +02:00
|
|
|
## Shift right by k.
|
|
|
|
##
|
|
|
|
## k MUST be less than the base word size (2^32 or 2^64)
|
|
|
|
# Note: for speed, loading a[i] and a[i+1]
|
|
|
|
# instead of a[i-1] and a[i]
|
|
|
|
# is probably easier to parallelize for the compiler
|
|
|
|
# (antidependence WAR vs loop-carried dependence RAW)
|
|
|
|
when cpuEndian == littleEndian:
|
|
|
|
for i in 0 ..< x.len-1:
|
|
|
|
result[i] = (x[i] shr k) or (x[i+1] shl (WordBitWidth - k))
|
|
|
|
result[^1] = x[^1] shr k
|
2018-04-20 11:13:47 +02:00
|
|
|
else:
|
2020-06-12 19:23:03 +02:00
|
|
|
for i in countdown(x.len-1, 1):
|
|
|
|
result[i] = (x[i] shr k) or (x[i-1] shl (WordBitWidth - k))
|
|
|
|
result[0] = x[0] shr k
|
|
|
|
|
2020-06-12 19:59:03 +02:00
|
|
|
func `shl`*(x: Limbs, k: SomeInteger): Limbs =
|
2020-06-12 19:23:03 +02:00
|
|
|
## Compute the `shift left` operation of x and k
|
|
|
|
when cpuEndian == littleEndian:
|
|
|
|
result[0] = x[0] shl k
|
|
|
|
for i in 1 ..< x.len:
|
|
|
|
result[i] = (x[i] shl k) or (x[i-1] shr (WordBitWidth - k))
|
2018-04-20 11:13:47 +02:00
|
|
|
else:
|
2020-06-12 19:23:03 +02:00
|
|
|
result[^1] = x[^1] shl k
|
|
|
|
for i in countdown(x.len-2, 0):
|
|
|
|
result[i] = (x[i] shl k) or (x[i+1] shr (WordBitWidth - k))
|