Merge pull request #340 from aeternity/add_bitwise_stdlib
Add Bitwise.aes to stdlib
This commit is contained in:
commit
ebb1f9ecf9
@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
|
- `Bitwise` stdlib
|
||||||
- `Set` stdlib
|
- `Set` stdlib
|
||||||
- `Option.force_msg`
|
- `Option.force_msg`
|
||||||
- Loading namespaces into the current scope (e.g. `using Pair`)
|
- Loading namespaces into the current scope (e.g. `using Pair`)
|
||||||
|
@ -37,6 +37,7 @@ include "List.aes"
|
|||||||
- [Func](#func)
|
- [Func](#func)
|
||||||
- [Pair](#pair)
|
- [Pair](#pair)
|
||||||
- [Triple](#triple)
|
- [Triple](#triple)
|
||||||
|
- [Bitwise](#bitwise)
|
||||||
- [BLS12_381](bls12_381)
|
- [BLS12_381](bls12_381)
|
||||||
- [Frac](#frac)
|
- [Frac](#frac)
|
||||||
- [Set](#set-stdlib)
|
- [Set](#set-stdlib)
|
||||||
@ -1294,7 +1295,7 @@ Escapes `option` wrapping by providing default value for `None`.
|
|||||||
Option.force(o : option('a)) : 'a
|
Option.force(o : option('a)) : 'a
|
||||||
```
|
```
|
||||||
|
|
||||||
Forcefully escapes the `option` wrapping assuming it is `Some`.
|
Forcefully escapes the `option` wrapping assuming it is `Some`.
|
||||||
Aborts on `None`.
|
Aborts on `None`.
|
||||||
|
|
||||||
|
|
||||||
@ -1817,6 +1818,90 @@ Triple.rotl(t : ('a * 'b * 'c)) : ('b * 'c * 'a)
|
|||||||
|
|
||||||
Cyclic rotation of the elements to the left.
|
Cyclic rotation of the elements to the left.
|
||||||
|
|
||||||
|
### Bitwise
|
||||||
|
|
||||||
|
Bitwise operations on arbitrary precision integers.
|
||||||
|
|
||||||
|
#### bsr
|
||||||
|
```
|
||||||
|
Bitwise.bsr(n : int, x : int) : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Logical bit shift `x` right `n` positions.
|
||||||
|
|
||||||
|
|
||||||
|
#### bsl
|
||||||
|
```
|
||||||
|
Bitwise.bsl(n : int, x : int) : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Logical bit shift `x` left `n` positions.
|
||||||
|
|
||||||
|
|
||||||
|
#### bsli
|
||||||
|
```
|
||||||
|
Bitwise.bsli(n : int, x : int, lim : int) : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Logical bit shift `x` left `n` positions, limit to `lim` bits.
|
||||||
|
|
||||||
|
|
||||||
|
#### band
|
||||||
|
```
|
||||||
|
Bitwise.band(x : int, y : int) : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Bitwise `and` of `x` and `y`.
|
||||||
|
|
||||||
|
|
||||||
|
#### bor
|
||||||
|
```
|
||||||
|
Bitwise.bor(x : int, y : int) : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Bitwise `or` of `x` and `y`.
|
||||||
|
|
||||||
|
|
||||||
|
#### bxor
|
||||||
|
```
|
||||||
|
Bitwise.bxor(x : int, y : int) : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Bitwise `xor` of `x` and `y`.
|
||||||
|
|
||||||
|
|
||||||
|
#### bnot
|
||||||
|
```
|
||||||
|
Bitwise.bnot(x : int) : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Bitwise `not` of `x`. Defined and implemented as `bnot(x) = bxor(x, -1)`.
|
||||||
|
|
||||||
|
|
||||||
|
#### uband
|
||||||
|
```
|
||||||
|
Bitwise.uband(x : int, y : int) : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Bitwise `and` of _non-negative_ numbers `x` and `y`.
|
||||||
|
|
||||||
|
|
||||||
|
#### ubor
|
||||||
|
```
|
||||||
|
Bitwise.ubor(x : int, y : int) : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Bitwise `or` of _non-negative_ `x` and `y`.
|
||||||
|
|
||||||
|
|
||||||
|
#### ubxor
|
||||||
|
```
|
||||||
|
Bitwise.ubxor(x : int, y : int) : int
|
||||||
|
```
|
||||||
|
|
||||||
|
Bitwise `xor` of _non-negative_ `x` and `y`.
|
||||||
|
|
||||||
|
|
||||||
### BLS12\_381
|
### BLS12\_381
|
||||||
|
|
||||||
#### Types
|
#### Types
|
||||||
|
136
priv/stdlib/Bitwise.aes
Normal file
136
priv/stdlib/Bitwise.aes
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
@compiler >= 4.3
|
||||||
|
|
||||||
|
namespace Bitwise =
|
||||||
|
|
||||||
|
// bit shift 'x' right 'n' postions
|
||||||
|
function bsr(n : int, x : int) : int =
|
||||||
|
let step = 2^n
|
||||||
|
let res = x / step
|
||||||
|
if (x >= 0 || x mod step == 0)
|
||||||
|
res
|
||||||
|
else
|
||||||
|
res - 1
|
||||||
|
|
||||||
|
// bit shift 'x' left 'n' positions
|
||||||
|
function bsl(n : int, x : int) : int =
|
||||||
|
x * 2^n
|
||||||
|
|
||||||
|
// bit shift 'x' left 'n' positions, limit at 'lim' bits
|
||||||
|
function bsli(n : int, x : int, lim : int) : int =
|
||||||
|
(x * 2^n) mod (2^lim)
|
||||||
|
|
||||||
|
// bitwise 'and' for arbitrary precision integers
|
||||||
|
function band(a : int, b : int) : int =
|
||||||
|
if (a >= 0 && b >= 0)
|
||||||
|
uband_(a, b)
|
||||||
|
elif (b >= 0)
|
||||||
|
ubnand_(b, -1 - a)
|
||||||
|
elif (a >= 0)
|
||||||
|
ubnand_(a, -1 - b)
|
||||||
|
else
|
||||||
|
-1 - ubor_(-1 - a, -1 - b)
|
||||||
|
|
||||||
|
// bitwise 'or' for arbitrary precision integers
|
||||||
|
function
|
||||||
|
bor : (int, int) => int
|
||||||
|
bor(0, b) = b
|
||||||
|
bor(a, 0) = a
|
||||||
|
bor(a : int, b : int) : int =
|
||||||
|
if (a >= 0 && b >= 0)
|
||||||
|
ubor_(a, b)
|
||||||
|
elif (b >= 0)
|
||||||
|
-1 - ubnand_(-1 - a, b)
|
||||||
|
elif (a >= 0)
|
||||||
|
-1 - ubnand_(-1 - b, a)
|
||||||
|
else
|
||||||
|
-1 - uband_(-1 - a, -1 - b)
|
||||||
|
|
||||||
|
// bitwise 'xor' for arbitrary precision integers
|
||||||
|
function
|
||||||
|
bxor : (int, int) => int
|
||||||
|
bxor(0, b) = b
|
||||||
|
bxor(a, 0) = a
|
||||||
|
bxor(a, b) =
|
||||||
|
if (a >= 0 && b >= 0)
|
||||||
|
ubxor_(a, b)
|
||||||
|
elif (b >= 0)
|
||||||
|
-1 - ubxor_(-1 - a, b)
|
||||||
|
elif (a >= 0)
|
||||||
|
-1 - ubxor_(a, -1 - b)
|
||||||
|
else
|
||||||
|
ubxor_(-1 - a, -1 - b)
|
||||||
|
|
||||||
|
// bitwise 'not' for arbitrary precision integers
|
||||||
|
function bnot(a : int) = bxor(a, -1)
|
||||||
|
|
||||||
|
// Bitwise 'and' for non-negative integers
|
||||||
|
function uband(a : int, b : int) : int =
|
||||||
|
require(a >= 0 && b >= 0, "uband is only defined for non-negative integers")
|
||||||
|
switch((a, b))
|
||||||
|
(0, _) => 0
|
||||||
|
(_, 0) => 0
|
||||||
|
_ => uband__(a, b, 1, 0)
|
||||||
|
|
||||||
|
private function uband_(a, b) = uband__(a, b, 1, 0)
|
||||||
|
|
||||||
|
private function
|
||||||
|
uband__(0, b, val, acc) = acc
|
||||||
|
uband__(a, 0, val, acc) = acc
|
||||||
|
uband__(a, b, val, acc) =
|
||||||
|
switch (a mod 2 + b mod 2)
|
||||||
|
2 => uband__(a / 2, b / 2, val * 2, acc + val)
|
||||||
|
_ => uband__(a / 2, b / 2, val * 2, acc)
|
||||||
|
|
||||||
|
// Bitwise 'or' for non-negative integers
|
||||||
|
function ubor(a, b) =
|
||||||
|
require(a >= 0 && b >= 0, "ubor is only defined for non-negative integers")
|
||||||
|
switch((a, b))
|
||||||
|
(0, _) => b
|
||||||
|
(_, 0) => a
|
||||||
|
_ => ubor__(a, b, 1, 0)
|
||||||
|
|
||||||
|
private function ubor_(a, b) = ubor__(a, b, 1, 0)
|
||||||
|
|
||||||
|
private function
|
||||||
|
ubor__(0, 0, val, acc) = acc
|
||||||
|
ubor__(a, b, val, acc) =
|
||||||
|
switch (a mod 2 + b mod 2)
|
||||||
|
0 => ubor__(a / 2, b / 2, val * 2, acc)
|
||||||
|
_ => ubor__(a / 2, b / 2, val * 2, acc + val)
|
||||||
|
|
||||||
|
//Bitwise 'xor' for non-negative integers
|
||||||
|
function
|
||||||
|
ubxor : (int, int) => int
|
||||||
|
ubxor(0, b) = b
|
||||||
|
ubxor(a, 0) = a
|
||||||
|
ubxor(a, b) =
|
||||||
|
require(a >= 0 && b >= 0, "ubxor is only defined for non-negative integers")
|
||||||
|
ubxor__(a, b, 1, 0)
|
||||||
|
|
||||||
|
private function ubxor_(a, b) = ubxor__(a, b, 1, 0)
|
||||||
|
|
||||||
|
private function
|
||||||
|
ubxor__(0, 0, val, acc) = acc
|
||||||
|
ubxor__(a, b, val, acc) =
|
||||||
|
switch(a mod 2 + b mod 2)
|
||||||
|
1 => ubxor__(a / 2, b / 2, val * 2, acc + val)
|
||||||
|
_ => ubxor__(a / 2, b / 2, val * 2, acc)
|
||||||
|
|
||||||
|
// Bitwise combined 'and' and 'not' of second argument for positive integers
|
||||||
|
// x 'bnand' y = x 'band' ('bnot' y)
|
||||||
|
// The tricky bit is that after negation the second argument has an infinite number of 1's
|
||||||
|
// use as many as needed!
|
||||||
|
//
|
||||||
|
// NOTE: this function is not symmetric!
|
||||||
|
private function ubnand(a, b) =
|
||||||
|
require(a >= 0 && b >= 0, "ubxor is only defined for non-negative integers")
|
||||||
|
ubnand__(a, b, 1, 0)
|
||||||
|
|
||||||
|
private function ubnand_(a, b) = ubnand__(a, b, 1, 0)
|
||||||
|
|
||||||
|
private function
|
||||||
|
ubnand__(0, b, val, acc) = acc
|
||||||
|
ubnand__(a, b, val, acc) =
|
||||||
|
switch((a mod 2, b mod 2))
|
||||||
|
(1, 0) => ubnand__(a / 2, b / 2, val * 2, acc + val)
|
||||||
|
_ => ubnand__(a / 2, b / 2, val * 2, acc)
|
Loading…
x
Reference in New Issue
Block a user