Fix power to result type, add tests, adjust docs
This commit is contained in:
parent
725f4b7289
commit
331f20e03a
35 changed files with 1734 additions and 447 deletions
4
CHANGELOG.txt
Normal file
4
CHANGELOG.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
1.0.0
|
||||
-----
|
||||
|
||||
* Initial release.
|
30
README.md
30
README.md
|
@ -41,7 +41,7 @@ latter will return an unranged big integer. An example with `ranged_int/builtin/
|
|||
where these functions are wrapped:
|
||||
|
||||
```gleam
|
||||
let assert Ok(a) = uint8.from_bigint(bigi.from_int(120))
|
||||
let assert Ok(a) = uint8.from_int(120)
|
||||
let b = bigi.from_int(160)
|
||||
uint8.overflow(uint8.add(a, b)) // Uint8(24)
|
||||
uint8.eject(uint8.add(a, b)) // BigInt(280)
|
||||
|
@ -51,12 +51,21 @@ uint8.eject(uint8.add(a, b)) // BigInt(280)
|
|||
|
||||
The overflow algorithm is based on how unsigned integer overflow is done in the C
|
||||
language. In C it is not defined for signed integers, but this library defines it for all
|
||||
ranged integers. In a nutshell:
|
||||
ranged integers, using 2's complement for the builtin signed integers. The formula for
|
||||
calculating the overflowed result is
|
||||
|
||||
1. Shift the range into a positive range, starting from 0.
|
||||
1. Shift the value to overflow the same amount.
|
||||
1. Do unsigned integer overflow or underflow.
|
||||
1. Shift the answer back to the original range.
|
||||
```
|
||||
(value - min) % amount_of_values + min
|
||||
```
|
||||
|
||||
where `min` is the minimum allowed value in the range, `amount_of_values` is the total
|
||||
amount of allowed values, and `%` is the modulo (not remainder) operation.
|
||||
|
||||
In effect, for types that represent unsigned integers or 2's complement signed integers,
|
||||
this is equivalent to truncating the value to the amount of bits that defines the range.
|
||||
|
||||
It's left up to the user to decide when overflowing makes sense, and to call `overflow`
|
||||
when appropriate.
|
||||
|
||||
## The builtin types
|
||||
|
||||
|
@ -173,7 +182,7 @@ pub fn mvp_add_test() {
|
|||
let assert Ok(a) = interface.from_bigint(bigi.from_int(2007), mvp.iface)
|
||||
let b = bigi.from_int(9)
|
||||
let c = interface.math_op(a, b, mvp.iface, bigi.add)
|
||||
should.equal(c, Error(utils.DidOverflow(bigi.from_int(1))))
|
||||
should.equal(c, Error(utils.WouldOverflow(bigi.from_int(1))))
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -229,7 +238,12 @@ pub fn mvp2_add_test() {
|
|||
let assert Ok(a) = mvp2.from_bigint(bigi.from_int(2007))
|
||||
let b = bigi.from_int(9)
|
||||
let c = mvp2.add(a, b)
|
||||
should.equal(c, Error(utils.DidOverflow(bigi.from_int(1))))
|
||||
should.equal(c, Error(utils.WouldOverflow(bigi.from_int(1))))
|
||||
should.equal(
|
||||
mvp2.overflow(c)
|
||||
|> mvp2.to_bigint(),
|
||||
bigi.from_int(2007),
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ repository = { type = "gitlab", user = "Nicd", repo = "ranged_int" }
|
|||
|
||||
[dependencies]
|
||||
gleam_stdlib = "~> 0.34 or ~> 1.0"
|
||||
bigi = "~> 1.0"
|
||||
bigi = "~> 2.0"
|
||||
|
||||
[dev-dependencies]
|
||||
gleeunit = "~> 1.0"
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
# You typically do not need to edit this file
|
||||
|
||||
packages = [
|
||||
{ name = "bigi", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "bigi", source = "hex", outer_checksum = "CB2766365C3DA3C651AD55F6A6389A586FA6B2D66B80BE0DA168EEBD0EE1A43D" },
|
||||
{ name = "bigi", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "bigi", source = "hex", outer_checksum = "E7841470F475D20B2EC2D4CB1167A8893AE943B6541809DCAB9D95FB471FDCDB" },
|
||||
{ name = "gleam_stdlib", version = "0.34.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "1FB8454D2991E9B4C0C804544D8A9AD0F6184725E20D63C3155F0AEB4230B016" },
|
||||
{ name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" },
|
||||
]
|
||||
|
||||
[requirements]
|
||||
bigi = { version = "~> 1.0"}
|
||||
bigi = { version = "~> 2.0" }
|
||||
gleam_stdlib = { version = "~> 0.34 or ~> 1.0" }
|
||||
gleeunit = { version = "~> 1.0" }
|
||||
|
|
|
@ -4,12 +4,10 @@
|
|||
//// compile time. Generic ranged integers are less type safe and have lower
|
||||
//// performance. It's always suggested to use one of the builtin types or to
|
||||
//// create your own type when you can.
|
||||
////
|
||||
//// Any two-operand math operations will use the range of the first operand as
|
||||
//// the range of the output value.
|
||||
|
||||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, type Overflowable, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
/// The interface of a generic ranged integer.
|
||||
pub opaque type GenericInterface(overflow_mode) {
|
||||
|
@ -79,16 +77,30 @@ pub fn divide(a: RangedInt(overflow_mode), b: BigInt) {
|
|||
interface.math_op(a, b, a.interface(), bigi.divide)
|
||||
}
|
||||
|
||||
pub fn divide_no_zero(a: RangedInt(overflow_mode), b: BigInt) {
|
||||
interface.fallible_op(a, b, a.interface(), bigi.divide_no_zero)
|
||||
}
|
||||
|
||||
pub fn modulo(a: RangedInt(overflow_mode), b: BigInt) {
|
||||
interface.math_op(a, b, a.interface(), bigi.modulo)
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero(a: RangedInt(overflow_mode), b: BigInt) {
|
||||
interface.fallible_op(a, b, a.interface(), bigi.modulo_no_zero)
|
||||
}
|
||||
|
||||
pub fn remainder(a: RangedInt(overflow_mode), b: BigInt) {
|
||||
interface.math_op(a, b, a.interface(), bigi.remainder)
|
||||
}
|
||||
|
||||
pub fn power(a: RangedInt(overflow_mode), b: BigInt) {
|
||||
interface.math_op(a, b, a.interface(), bigi.power)
|
||||
pub fn remainder_no_zero(a: RangedInt(overflow_mode), b: BigInt) {
|
||||
interface.fallible_op(a, b, a.interface(), bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: RangedInt(overflow_mode), b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), a.interface(), bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
pub opaque type Int128 {
|
||||
Int128(data: BigInt)
|
||||
|
@ -63,8 +64,10 @@ pub fn remainder_no_zero(a: Int128, b: BigInt) {
|
|||
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: Int128, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Int128, b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(op: interface.OpResult(Int128)) {
|
||||
|
@ -76,11 +79,8 @@ pub fn eject(op: interface.OpResult(Int128)) {
|
|||
}
|
||||
|
||||
fn limits() {
|
||||
let min =
|
||||
bigi.multiply(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(127)),
|
||||
bigi.from_int(-1),
|
||||
)
|
||||
let assert Ok(b127) = bigi.power(bigi.from_int(2), bigi.from_int(127))
|
||||
let min = bigi.multiply(b127, bigi.from_int(-1))
|
||||
let max = bigi.subtract(bigi.absolute(min), bigi.from_int(1))
|
||||
|
||||
interface.overflowable_limits(min, max)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const max_limit = 32_767
|
||||
|
||||
|
@ -79,8 +80,10 @@ pub fn remainder_no_zero(a: Int16, b: BigInt) {
|
|||
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: Int16, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Int16, b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(op: interface.OpResult(Int16)) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const max_limit = 2_147_483_647
|
||||
|
||||
|
@ -79,8 +80,10 @@ pub fn remainder_no_zero(a: Int32, b: BigInt) {
|
|||
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: Int32, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Int32, b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(op: interface.OpResult(Int32)) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
pub opaque type Int64 {
|
||||
Int64(data: BigInt)
|
||||
|
@ -63,8 +64,10 @@ pub fn remainder_no_zero(a: Int64, b: BigInt) {
|
|||
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: Int64, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Int64, b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(op: interface.OpResult(Int64)) {
|
||||
|
@ -76,11 +79,8 @@ pub fn eject(op: interface.OpResult(Int64)) {
|
|||
}
|
||||
|
||||
fn limits() {
|
||||
let min =
|
||||
bigi.multiply(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(63)),
|
||||
bigi.from_int(-1),
|
||||
)
|
||||
let assert Ok(b63) = bigi.power(bigi.from_int(2), bigi.from_int(63))
|
||||
let min = bigi.multiply(b63, bigi.from_int(-1))
|
||||
let max = bigi.subtract(bigi.absolute(min), bigi.from_int(1))
|
||||
|
||||
interface.overflowable_limits(min, max)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const max_limit = 127
|
||||
|
||||
|
@ -79,8 +80,10 @@ pub fn remainder_no_zero(a: Int8, b: BigInt) {
|
|||
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: Int8, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Int8, b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(op: interface.OpResult(Int8)) {
|
||||
|
|
|
@ -51,8 +51,10 @@ pub fn remainder(a: Uint, b: BigInt) {
|
|||
interface.math_op(a, b, iface, bigi.remainder)
|
||||
}
|
||||
|
||||
pub fn power(a: Uint, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Uint, b: Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn eject(op: interface.OpResult(Uint)) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
pub opaque type Uint128 {
|
||||
Uint128(data: BigInt)
|
||||
|
@ -59,8 +60,10 @@ pub fn remainder_no_zero(a: Uint128, b: BigInt) {
|
|||
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: Uint128, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Uint128, b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(op: interface.OpResult(Uint128)) {
|
||||
|
@ -73,11 +76,8 @@ pub fn eject(op: interface.OpResult(Uint128)) {
|
|||
|
||||
fn limits() {
|
||||
let min = bigi.zero()
|
||||
let max =
|
||||
bigi.subtract(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(128)),
|
||||
bigi.from_int(1),
|
||||
)
|
||||
let assert Ok(b128) = bigi.power(bigi.from_int(2), bigi.from_int(128))
|
||||
let max = bigi.subtract(b128, bigi.from_int(1))
|
||||
|
||||
interface.overflowable_limits(min, max)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const max_limit = 65_535
|
||||
|
||||
|
@ -75,8 +76,10 @@ pub fn remainder_no_zero(a: Uint16, b: BigInt) {
|
|||
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: Uint16, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Uint16, b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(op: interface.OpResult(Uint16)) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
pub const max_limit = 4_294_967_295
|
||||
|
||||
|
@ -75,8 +76,10 @@ pub fn remainder_no_zero(a: Uint32, b: BigInt) {
|
|||
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: Uint32, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Uint32, b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(op: interface.OpResult(Uint32)) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
pub opaque type Uint64 {
|
||||
Uint64(data: BigInt)
|
||||
|
@ -59,8 +60,10 @@ pub fn remainder_no_zero(a: Uint64, b: BigInt) {
|
|||
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: Uint64, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Uint64, b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(op: interface.OpResult(Uint64)) {
|
||||
|
@ -73,11 +76,8 @@ pub fn eject(op: interface.OpResult(Uint64)) {
|
|||
|
||||
fn limits() {
|
||||
let min = bigi.zero()
|
||||
let max =
|
||||
bigi.subtract(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(64)),
|
||||
bigi.from_int(1),
|
||||
)
|
||||
let assert Ok(b64) = bigi.power(bigi.from_int(2), bigi.from_int(64))
|
||||
let max = bigi.subtract(b64, bigi.from_int(1))
|
||||
|
||||
interface.overflowable_limits(min, max)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bigi.{type BigInt}
|
||||
import ranged_int/interface.{type Interface, Interface}
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const max_limit = 255
|
||||
|
||||
|
@ -75,8 +76,10 @@ pub fn remainder_no_zero(a: Uint8, b: BigInt) {
|
|||
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
|
||||
}
|
||||
|
||||
pub fn power(a: Uint8, b: BigInt) {
|
||||
interface.math_op(a, b, iface, bigi.power)
|
||||
pub fn power(a: Uint8, b: uint.Uint) {
|
||||
let assert Ok(result) =
|
||||
interface.fallible_op(a, uint.to_bigint(b), iface, bigi.power)
|
||||
result
|
||||
}
|
||||
|
||||
pub fn overflow(op: interface.OpResult(Uint8)) {
|
||||
|
|
|
@ -85,8 +85,8 @@ pub fn from_bigint(
|
|||
let limits = interface.limits()
|
||||
case limit.check_limits(value, min: limits.min, max: limits.max) {
|
||||
NoOverflow -> Ok(interface.from_bigint_unsafe(value))
|
||||
Overflow(amount) -> Error(utils.DidOverflow(amount))
|
||||
Underflow(amount) -> Error(utils.DidUnderflow(amount))
|
||||
Overflow(amount) -> Error(utils.WouldOverflow(amount))
|
||||
Underflow(amount) -> Error(utils.WouldUnderflow(amount))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,8 +111,8 @@ pub fn math_op(
|
|||
let result = op(int1, int2)
|
||||
case limit.check_limits(result, min: limits.min, max: limits.max) {
|
||||
NoOverflow -> Ok(interface.from_bigint_unsafe(result))
|
||||
Overflow(amount) -> Error(utils.DidOverflow(amount))
|
||||
Underflow(amount) -> Error(utils.DidUnderflow(amount))
|
||||
Overflow(amount) -> Error(utils.WouldOverflow(amount))
|
||||
Underflow(amount) -> Error(utils.WouldUnderflow(amount))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,8 +127,8 @@ pub fn math_op_unary(
|
|||
let result = op(int)
|
||||
case limit.check_limits(result, min: limits.min, max: limits.max) {
|
||||
NoOverflow -> Ok(interface.from_bigint_unsafe(result))
|
||||
Overflow(amount) -> Error(utils.DidOverflow(amount))
|
||||
Underflow(amount) -> Error(utils.DidUnderflow(amount))
|
||||
Overflow(amount) -> Error(utils.WouldOverflow(amount))
|
||||
Underflow(amount) -> Error(utils.WouldUnderflow(amount))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,8 +148,8 @@ pub fn fallible_op(
|
|||
use result <- result.try(op(int1, int2))
|
||||
Ok(case limit.check_limits(result, min: limits.min, max: limits.max) {
|
||||
NoOverflow -> Ok(interface.from_bigint_unsafe(result))
|
||||
Overflow(amount) -> Error(utils.DidOverflow(amount))
|
||||
Underflow(amount) -> Error(utils.DidUnderflow(amount))
|
||||
Overflow(amount) -> Error(utils.WouldOverflow(amount))
|
||||
Underflow(amount) -> Error(utils.WouldUnderflow(amount))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -178,9 +178,9 @@ pub fn eject(value: OpResult(a), interface: Interface(a, overflow_mode)) {
|
|||
Ok(new_value) -> interface.to_bigint(new_value)
|
||||
Error(overflow) -> {
|
||||
case overflow, interface.limits() {
|
||||
utils.DidOverflow(amount), Limits(max: limit.Bounded(max), ..) ->
|
||||
utils.WouldOverflow(amount), Limits(max: limit.Bounded(max), ..) ->
|
||||
bigi.add(max, amount)
|
||||
utils.DidUnderflow(amount), Limits(min: limit.Bounded(min), ..) ->
|
||||
utils.WouldUnderflow(amount), Limits(min: limit.Bounded(min), ..) ->
|
||||
bigi.subtract(min, amount)
|
||||
_, _ -> panic as "Overflowed but there was no corresponding limit (o_O)"
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@ import bigi.{type BigInt}
|
|||
/// range.
|
||||
pub type Overflow {
|
||||
/// The result was this much higher than the maximum allowed value.
|
||||
DidOverflow(BigInt)
|
||||
WouldOverflow(BigInt)
|
||||
/// The result was this much lower than the minimum allowed value.
|
||||
DidUnderflow(BigInt)
|
||||
WouldUnderflow(BigInt)
|
||||
}
|
||||
|
||||
/// Calculate the overflowed value given an overflow result and the limits.
|
||||
|
@ -15,15 +15,13 @@ pub fn overflow(overflow: Overflow, min min: BigInt, max max: BigInt) -> BigInt
|
|||
bigi.subtract(max, min)
|
||||
|> bigi.add(bigi.from_int(1))
|
||||
|
||||
let min_adjustment_factor = bigi.multiply(min, bigi.from_int(-1))
|
||||
let adjusted_max = bigi.add(max, min_adjustment_factor)
|
||||
let adjusted_min = bigi.zero()
|
||||
|
||||
let overflowed_value = case overflow {
|
||||
DidOverflow(amount) -> bigi.add(adjusted_max, amount)
|
||||
DidUnderflow(amount) -> bigi.subtract(adjusted_min, amount)
|
||||
let actual = case overflow {
|
||||
WouldOverflow(amount) -> bigi.add(max, amount)
|
||||
WouldUnderflow(amount) -> bigi.subtract(min, amount)
|
||||
}
|
||||
|
||||
let overflow_result = bigi.modulo(overflowed_value, total_values)
|
||||
bigi.subtract(overflow_result, min_adjustment_factor)
|
||||
actual
|
||||
|> bigi.subtract(min)
|
||||
|> bigi.modulo(total_values)
|
||||
|> bigi.add(min)
|
||||
}
|
||||
|
|
|
@ -1,326 +0,0 @@
|
|||
import gleam/function
|
||||
import gleeunit/should
|
||||
import bigi.{type BigInt}
|
||||
import ranged_int/interface
|
||||
import ranged_int/builtin/uint8
|
||||
import ranged_int/builtin/uint16
|
||||
import ranged_int/builtin/uint32
|
||||
import ranged_int/builtin/uint64
|
||||
import ranged_int/builtin/uint128
|
||||
import ranged_int/builtin/int8
|
||||
import ranged_int/builtin/int16
|
||||
import ranged_int/builtin/int32
|
||||
import ranged_int/builtin/int64
|
||||
import ranged_int/builtin/int128
|
||||
|
||||
pub fn absolute_test() {
|
||||
let input = bigi.from_int(-19)
|
||||
let expected = bigi.from_int(19)
|
||||
|
||||
unary(int8.from_bigint, int8.absolute)(input, expected)
|
||||
unary(int16.from_bigint, int16.absolute)(input, expected)
|
||||
unary(int32.from_bigint, int32.absolute)(input, expected)
|
||||
unary(int64.from_bigint, int64.absolute)(input, expected)
|
||||
unary(int128.from_bigint, int128.absolute)(input, expected)
|
||||
}
|
||||
|
||||
pub fn add_test() {
|
||||
let input1 = bigi.from_int(1)
|
||||
let input2 = bigi.from_int(12)
|
||||
let expected = bigi.from_int(13)
|
||||
|
||||
binary(int8.from_bigint, int8.add)(
|
||||
input1,
|
||||
input2,
|
||||
should.equal(_, int8.from_bigint(expected)),
|
||||
)
|
||||
binary(int16.from_bigint, int16.add)(
|
||||
input1,
|
||||
input2,
|
||||
should.equal(_, int16.from_bigint(expected)),
|
||||
)
|
||||
binary(int32.from_bigint, int32.add)(
|
||||
input1,
|
||||
input2,
|
||||
should.equal(_, int32.from_bigint(expected)),
|
||||
)
|
||||
binary(int64.from_bigint, int64.add)(
|
||||
input1,
|
||||
input2,
|
||||
should.equal(_, int64.from_bigint(expected)),
|
||||
)
|
||||
binary(int128.from_bigint, int128.add)(
|
||||
input1,
|
||||
input2,
|
||||
should.equal(_, int128.from_bigint(expected)),
|
||||
)
|
||||
binary(uint8.from_bigint, uint8.add)(
|
||||
input1,
|
||||
input2,
|
||||
should.equal(_, uint8.from_bigint(expected)),
|
||||
)
|
||||
binary(uint16.from_bigint, uint16.add)(
|
||||
input1,
|
||||
input2,
|
||||
should.equal(_, uint16.from_bigint(expected)),
|
||||
)
|
||||
binary(uint32.from_bigint, uint32.add)(
|
||||
input1,
|
||||
input2,
|
||||
should.equal(_, uint32.from_bigint(expected)),
|
||||
)
|
||||
binary(uint64.from_bigint, uint64.add)(
|
||||
input1,
|
||||
input2,
|
||||
should.equal(_, uint64.from_bigint(expected)),
|
||||
)
|
||||
binary(uint128.from_bigint, uint128.add)(
|
||||
input1,
|
||||
input2,
|
||||
should.equal(_, uint128.from_bigint(expected)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn add_overflow_test() {
|
||||
let input1 = bigi.zero()
|
||||
let input2 = bigi.power(bigi.from_int(2), bigi.from_int(1024))
|
||||
|
||||
binary(int8.from_bigint, int8.add)(input1, input2, should.be_error)
|
||||
binary(int16.from_bigint, int16.add)(input1, input2, should.be_error)
|
||||
binary(int32.from_bigint, int32.add)(input1, input2, should.be_error)
|
||||
binary(int64.from_bigint, int64.add)(input1, input2, should.be_error)
|
||||
binary(int128.from_bigint, int128.add)(input1, input2, should.be_error)
|
||||
binary(uint8.from_bigint, uint8.add)(input1, input2, should.be_error)
|
||||
binary(uint16.from_bigint, uint16.add)(input1, input2, should.be_error)
|
||||
binary(uint32.from_bigint, uint32.add)(input1, input2, should.be_error)
|
||||
binary(uint64.from_bigint, uint64.add)(input1, input2, should.be_error)
|
||||
binary(uint128.from_bigint, uint128.add)(input1, input2, should.be_error)
|
||||
}
|
||||
|
||||
pub fn add_overflow_eject_test() {
|
||||
binary(int8.from_bigint, int8.add)(
|
||||
bigi.from_int(-127),
|
||||
bigi.from_int(1000),
|
||||
function.compose(int8.eject, should.equal(_, bigi.from_int(873))),
|
||||
)
|
||||
|
||||
binary(int16.from_bigint, int16.add)(
|
||||
bigi.from_int(32_767),
|
||||
bigi.from_int(1),
|
||||
function.compose(int16.eject, should.equal(_, bigi.from_int(32_768))),
|
||||
)
|
||||
|
||||
binary(int32.from_bigint, int32.add)(
|
||||
bigi.from_int(2_000_000_000),
|
||||
bigi.from_int(3_000_000_000),
|
||||
function.compose(int32.eject, should.equal(_, bigi.from_int(5_000_000_000))),
|
||||
)
|
||||
|
||||
binary(int64.from_bigint, int64.add)(
|
||||
bigi.subtract(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(63)),
|
||||
bigi.from_int(1),
|
||||
),
|
||||
bigi.from_int(1),
|
||||
function.compose(int64.eject, should.equal(_, bigi.power(
|
||||
bigi.from_int(2),
|
||||
bigi.from_int(63),
|
||||
))),
|
||||
)
|
||||
|
||||
binary(int128.from_bigint, int128.add)(
|
||||
bigi.subtract(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(127)),
|
||||
bigi.from_int(1),
|
||||
),
|
||||
bigi.from_int(1),
|
||||
function.compose(int128.eject, should.equal(_, bigi.power(
|
||||
bigi.from_int(2),
|
||||
bigi.from_int(127),
|
||||
))),
|
||||
)
|
||||
|
||||
binary(uint8.from_bigint, uint8.add)(
|
||||
bigi.from_int(0),
|
||||
bigi.from_int(1000),
|
||||
function.compose(uint8.eject, should.equal(_, bigi.from_int(1000))),
|
||||
)
|
||||
|
||||
binary(uint16.from_bigint, uint16.add)(
|
||||
bigi.from_int(32_768),
|
||||
bigi.from_int(32_768),
|
||||
function.compose(uint16.eject, should.equal(_, bigi.from_int(65_536))),
|
||||
)
|
||||
|
||||
binary(uint32.from_bigint, uint32.add)(
|
||||
bigi.from_int(2_000_000_000),
|
||||
bigi.from_int(3_000_000_000),
|
||||
function.compose(uint32.eject, should.equal(_, bigi.from_int(5_000_000_000))),
|
||||
)
|
||||
|
||||
binary(uint64.from_bigint, uint64.add)(
|
||||
bigi.subtract(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(64)),
|
||||
bigi.from_int(1),
|
||||
),
|
||||
bigi.from_int(1),
|
||||
function.compose(uint64.eject, should.equal(_, bigi.power(
|
||||
bigi.from_int(2),
|
||||
bigi.from_int(64),
|
||||
))),
|
||||
)
|
||||
|
||||
binary(uint128.from_bigint, uint128.add)(
|
||||
bigi.subtract(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(128)),
|
||||
bigi.from_int(1),
|
||||
),
|
||||
bigi.from_int(1),
|
||||
function.compose(uint128.eject, should.equal(_, bigi.power(
|
||||
bigi.from_int(2),
|
||||
bigi.from_int(128),
|
||||
))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn add_overflow_wrap_test() {
|
||||
overflow_wrap(
|
||||
bigi.from_int(127),
|
||||
bigi.from_int(1),
|
||||
bigi.from_int(-128),
|
||||
int8.from_bigint,
|
||||
int8.add,
|
||||
int8.overflow,
|
||||
)
|
||||
|
||||
overflow_wrap(
|
||||
bigi.from_int(-32_768),
|
||||
bigi.from_int(-1),
|
||||
bigi.from_int(32_767),
|
||||
int16.from_bigint,
|
||||
int16.add,
|
||||
int16.overflow,
|
||||
)
|
||||
|
||||
overflow_wrap(
|
||||
bigi.from_int(2_000_000_000),
|
||||
bigi.from_int(3_000_000_000),
|
||||
bigi.from_int(705_032_704),
|
||||
int32.from_bigint,
|
||||
int32.add,
|
||||
int32.overflow,
|
||||
)
|
||||
|
||||
overflow_wrap(
|
||||
bigi.subtract(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(63)),
|
||||
bigi.from_int(255),
|
||||
),
|
||||
bigi.from_int(255),
|
||||
bigi.multiply(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(63)),
|
||||
bigi.from_int(-1),
|
||||
),
|
||||
int64.from_bigint,
|
||||
int64.add,
|
||||
int64.overflow,
|
||||
)
|
||||
|
||||
overflow_wrap(
|
||||
bigi.multiply(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(127)),
|
||||
bigi.from_int(-1),
|
||||
),
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(128)),
|
||||
bigi.multiply(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(127)),
|
||||
bigi.from_int(-1),
|
||||
),
|
||||
int128.from_bigint,
|
||||
int128.add,
|
||||
int128.overflow,
|
||||
)
|
||||
|
||||
overflow_wrap(
|
||||
bigi.from_int(255),
|
||||
bigi.from_int(1),
|
||||
bigi.zero(),
|
||||
uint8.from_bigint,
|
||||
uint8.add,
|
||||
uint8.overflow,
|
||||
)
|
||||
|
||||
overflow_wrap(
|
||||
bigi.from_int(65_535),
|
||||
bigi.from_int(1),
|
||||
bigi.zero(),
|
||||
uint16.from_bigint,
|
||||
uint16.add,
|
||||
uint16.overflow,
|
||||
)
|
||||
|
||||
overflow_wrap(
|
||||
bigi.from_int(2_000_000_000),
|
||||
bigi.from_int(3_000_000_000),
|
||||
bigi.from_int(705_032_704),
|
||||
uint32.from_bigint,
|
||||
uint32.add,
|
||||
uint32.overflow,
|
||||
)
|
||||
|
||||
overflow_wrap(
|
||||
bigi.subtract(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(64)),
|
||||
bigi.from_int(1),
|
||||
),
|
||||
bigi.from_int(1),
|
||||
bigi.zero(),
|
||||
uint64.from_bigint,
|
||||
uint64.add,
|
||||
uint64.overflow,
|
||||
)
|
||||
|
||||
overflow_wrap(
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(127)),
|
||||
bigi.power(bigi.from_int(2), bigi.from_int(127)),
|
||||
bigi.zero(),
|
||||
uint128.from_bigint,
|
||||
uint128.add,
|
||||
uint128.overflow,
|
||||
)
|
||||
}
|
||||
|
||||
fn overflow_wrap(
|
||||
int1: BigInt,
|
||||
int2: BigInt,
|
||||
expected: BigInt,
|
||||
from_bigint: fn(BigInt) -> Result(a, b),
|
||||
fun: fn(a, BigInt) -> interface.OpResult(a),
|
||||
overflow: fn(interface.OpResult(a)) -> a,
|
||||
) {
|
||||
let assert Ok(expected) = from_bigint(expected)
|
||||
should.equal(binary(from_bigint, fun)(int1, int2, overflow), expected)
|
||||
}
|
||||
|
||||
fn unary(
|
||||
from_bigint: fn(BigInt) -> Result(a, b),
|
||||
fun: fn(a) -> interface.OpResult(a),
|
||||
) {
|
||||
fn(val: BigInt, expected: BigInt) {
|
||||
let assert Ok(val) = from_bigint(val)
|
||||
let assert Ok(expected) = from_bigint(expected)
|
||||
let res = fun(val)
|
||||
should.equal(res, Ok(expected))
|
||||
}
|
||||
}
|
||||
|
||||
fn binary(
|
||||
from_bigint: fn(BigInt) -> Result(a, b),
|
||||
fun: fn(a, BigInt) -> interface.OpResult(a),
|
||||
) {
|
||||
fn(val1: BigInt, val2: BigInt, check: fn(interface.OpResult(a)) -> any) {
|
||||
let assert Ok(val1) = from_bigint(val1)
|
||||
let res = fun(val1, val2)
|
||||
check(res)
|
||||
}
|
||||
}
|
|
@ -1,24 +1,116 @@
|
|||
import gleam/int
|
||||
import gleam/float
|
||||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/generic
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const min = -31_495
|
||||
|
||||
const max = -13_413
|
||||
|
||||
pub fn absolute_test() {
|
||||
let int = from_int(min)
|
||||
should.equal(
|
||||
generic.to_bigint(generic.overflow(
|
||||
generic.absolute(int),
|
||||
generic.get_interface(int),
|
||||
)),
|
||||
bigi.from_int(-22_754),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(a) = generic.from_bigint_min(bigi.zero(), min: bigi.zero())
|
||||
let b = bigi.from_int(12)
|
||||
let iface = generic.get_interface(a)
|
||||
let c = generic.eject(generic.add(a, b), iface)
|
||||
should.equal(c, bigi.from_int(12))
|
||||
let int1 = from_int(min)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(result) = generic.add(int1, int2)
|
||||
should.equal(generic.to_bigint(result), bigi.from_int(min + 1))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let assert Ok(a) =
|
||||
generic.from_bigint_overflowable(
|
||||
bigi.from_int(-15),
|
||||
min: bigi.from_int(-284),
|
||||
max: bigi.from_int(-7),
|
||||
)
|
||||
let b = bigi.from_int(12)
|
||||
let iface = generic.get_interface(a)
|
||||
let c = generic.overflow(generic.add(a, b), iface)
|
||||
should.equal(generic.to_bigint(c), bigi.from_int(-281))
|
||||
pub fn subtract_test() {
|
||||
let int1 = from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(result) = generic.subtract(int1, int2)
|
||||
should.equal(generic.to_bigint(result), bigi.from_int(max - 1))
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let int1 = from_int(max)
|
||||
let int2 = bigi.from_int(2)
|
||||
let assert Ok(result) = generic.multiply(int1, int2)
|
||||
should.equal(generic.to_bigint(result), bigi.from_int(max * 2))
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let int1 = from_int(min)
|
||||
let int2 = bigi.from_int(2)
|
||||
let assert Ok(result) = generic.divide(int1, int2)
|
||||
should.equal(generic.to_bigint(result), bigi.from_int(min / 2))
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let int1 = from_int(min)
|
||||
should.be_error(generic.divide_no_zero(int1, bigi.zero()))
|
||||
let assert Ok(Ok(result)) = generic.divide_no_zero(int1, bigi.from_int(2))
|
||||
should.equal(generic.to_bigint(result), bigi.from_int(min / 2))
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let int1 = from_int(min)
|
||||
let int2 = bigi.from_int(2)
|
||||
should.equal(
|
||||
generic.eject(generic.modulo(int1, int2), generic.get_interface(int1)),
|
||||
bigi.from_int(1),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let int1 = from_int(min)
|
||||
should.be_error(generic.modulo_no_zero(int1, bigi.zero()))
|
||||
let assert Ok(rem) = generic.modulo_no_zero(int1, bigi.from_int(2))
|
||||
should.equal(
|
||||
generic.eject(rem, generic.get_interface(int1)),
|
||||
bigi.from_int(1),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let int1 = from_int(min)
|
||||
let int2 = bigi.from_int(2)
|
||||
should.equal(
|
||||
generic.eject(generic.remainder(int1, int2), generic.get_interface(int1)),
|
||||
bigi.from_int(-1),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let int1 = from_int(min)
|
||||
should.be_error(generic.remainder_no_zero(int1, bigi.zero()))
|
||||
let assert Ok(rem) = generic.remainder_no_zero(int1, bigi.from_int(2))
|
||||
should.equal(
|
||||
generic.eject(rem, generic.get_interface(int1)),
|
||||
bigi.from_int(-1),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let int1 = from_int(max)
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
let assert Ok(expected) = int.power(max, 2.0)
|
||||
should.equal(
|
||||
generic.eject(generic.power(int1, int2), generic.get_interface(int1)),
|
||||
bigi.from_int(float.truncate(expected)),
|
||||
)
|
||||
}
|
||||
|
||||
fn from_int(int: Int) {
|
||||
let min = bigi.from_int(min)
|
||||
let max = bigi.from_int(max)
|
||||
|
||||
let assert Ok(int) =
|
||||
int
|
||||
|> bigi.from_int()
|
||||
|> generic.from_bigint_overflowable(min: min, max: max)
|
||||
|
||||
int
|
||||
}
|
||||
|
|
|
@ -1,9 +1,113 @@
|
|||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/int128
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
pub fn absolute_test() {
|
||||
let assert Ok(int) = int128.from_bigint(bigi.from_int(-1))
|
||||
should.equal(int128.absolute(int), int128.from_bigint(bigi.from_int(1)))
|
||||
}
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(a) = int128.from_bigint(bigi.from_int(-3_190_309_415))
|
||||
let b = int128.absolute(a)
|
||||
should.equal(b, int128.from_bigint(bigi.from_int(3_190_309_415)))
|
||||
let assert Ok(int1) = int128.from_bigint(bigi.from_int(-1))
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(int128.add(int1, int2), int128.from_bigint(bigi.from_int(0)))
|
||||
}
|
||||
|
||||
pub fn subtract_test() {
|
||||
let assert Ok(int1) = int128.from_bigint(bigi.from_int(-1))
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(
|
||||
int128.subtract(int1, int2),
|
||||
int128.from_bigint(bigi.from_int(-2)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let assert Ok(int1) = int128.from_bigint(bigi.from_int(2))
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(
|
||||
int128.multiply(int1, int2),
|
||||
int128.from_bigint(bigi.from_int(4)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let assert Ok(int1) = int128.from_bigint(bigi.from_int(-2))
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int128.divide(int1, int2), int128.from_bigint(bigi.from_int(1)))
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let assert Ok(int1) = int128.from_bigint(bigi.from_int(2))
|
||||
should.be_error(int128.divide_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int128.divide_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int128.from_bigint(bigi.from_int(1))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let assert Ok(int1) = int128.from_bigint(bigi.from_int(-2))
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int128.modulo(int1, int2), int128.from_bigint(bigi.from_int(0)))
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let assert Ok(int1) = int128.from_bigint(bigi.from_int(2))
|
||||
should.be_error(int128.modulo_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int128.modulo_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int128.from_bigint(bigi.from_int(0))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let assert Ok(int1) = int128.from_bigint(bigi.from_int(-2))
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(
|
||||
int128.remainder(int1, int2),
|
||||
int128.from_bigint(bigi.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let assert Ok(int1) = int128.from_bigint(bigi.from_int(2))
|
||||
should.be_error(int128.remainder_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int128.remainder_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int128.from_bigint(bigi.from_int(0))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let assert Ok(int1) = int128.from_bigint(bigi.from_int(-2))
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
should.equal(int128.power(int1, int2), int128.from_bigint(bigi.from_int(4)))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let #(min, max) = minmax()
|
||||
let assert Ok(int1) = int128.from_bigint(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(expected) = int128.from_bigint(min)
|
||||
should.equal(int128.overflow(int128.add(int1, int2)), expected)
|
||||
}
|
||||
|
||||
pub fn eject_test() {
|
||||
let #(_min, max) = minmax()
|
||||
let assert Ok(int1) = int128.from_bigint(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
should.equal(
|
||||
int128.eject(int128.add(int1, int2)),
|
||||
bigi.add(max, bigi.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
fn minmax() {
|
||||
let assert Ok(b127) = bigi.power(bigi.from_int(2), bigi.from_int(127))
|
||||
let min = bigi.multiply(b127, bigi.from_int(-1))
|
||||
let max = bigi.subtract(bigi.absolute(min), bigi.from_int(1))
|
||||
|
||||
#(min, max)
|
||||
}
|
||||
|
|
95
test/builtin/int16_test.gleam
Normal file
95
test/builtin/int16_test.gleam
Normal file
|
@ -0,0 +1,95 @@
|
|||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/int16
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const min = -32_768
|
||||
|
||||
const max = 32_767
|
||||
|
||||
pub fn absolute_test() {
|
||||
let assert Ok(int) = int16.from_int(-1)
|
||||
should.equal(int16.absolute(int), int16.from_int(1))
|
||||
}
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(int1) = int16.from_int(-1)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(int16.add(int1, int2), int16.from_int(0))
|
||||
}
|
||||
|
||||
pub fn subtract_test() {
|
||||
let assert Ok(int1) = int16.from_int(-1)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(int16.subtract(int1, int2), int16.from_int(-2))
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let assert Ok(int1) = int16.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(int16.multiply(int1, int2), int16.from_int(4))
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let assert Ok(int1) = int16.from_int(-2)
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int16.divide(int1, int2), int16.from_int(1))
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let assert Ok(int1) = int16.from_int(2)
|
||||
should.be_error(int16.divide_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int16.divide_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int16.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let assert Ok(int1) = int16.from_int(-2)
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int16.modulo(int1, int2), int16.from_int(0))
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let assert Ok(int1) = int16.from_int(2)
|
||||
should.be_error(int16.modulo_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int16.modulo_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int16.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let assert Ok(int1) = int16.from_int(-2)
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int16.remainder(int1, int2), int16.from_int(0))
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let assert Ok(int1) = int16.from_int(2)
|
||||
should.be_error(int16.remainder_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int16.remainder_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int16.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let assert Ok(int1) = int16.from_int(-2)
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
should.equal(int16.power(int1, int2), int16.from_int(4))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let assert Ok(int1) = int16.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(expected) = int16.from_int(min)
|
||||
should.equal(int16.overflow(int16.add(int1, int2)), expected)
|
||||
}
|
||||
|
||||
pub fn eject_test() {
|
||||
let assert Ok(int1) = int16.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
should.equal(int16.eject(int16.add(int1, int2)), bigi.from_int(max + 1))
|
||||
}
|
95
test/builtin/int32_test.gleam
Normal file
95
test/builtin/int32_test.gleam
Normal file
|
@ -0,0 +1,95 @@
|
|||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/int32
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const min = -2_147_483_648
|
||||
|
||||
const max = 2_147_483_647
|
||||
|
||||
pub fn absolute_test() {
|
||||
let assert Ok(int) = int32.from_int(-1)
|
||||
should.equal(int32.absolute(int), int32.from_int(1))
|
||||
}
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(int1) = int32.from_int(-1)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(int32.add(int1, int2), int32.from_int(0))
|
||||
}
|
||||
|
||||
pub fn subtract_test() {
|
||||
let assert Ok(int1) = int32.from_int(-1)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(int32.subtract(int1, int2), int32.from_int(-2))
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let assert Ok(int1) = int32.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(int32.multiply(int1, int2), int32.from_int(4))
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let assert Ok(int1) = int32.from_int(-2)
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int32.divide(int1, int2), int32.from_int(1))
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let assert Ok(int1) = int32.from_int(2)
|
||||
should.be_error(int32.divide_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int32.divide_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int32.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let assert Ok(int1) = int32.from_int(-2)
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int32.modulo(int1, int2), int32.from_int(0))
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let assert Ok(int1) = int32.from_int(2)
|
||||
should.be_error(int32.modulo_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int32.modulo_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int32.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let assert Ok(int1) = int32.from_int(-2)
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int32.remainder(int1, int2), int32.from_int(0))
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let assert Ok(int1) = int32.from_int(2)
|
||||
should.be_error(int32.remainder_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int32.remainder_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int32.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let assert Ok(int1) = int32.from_int(-2)
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
should.equal(int32.power(int1, int2), int32.from_int(4))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let assert Ok(int1) = int32.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(expected) = int32.from_int(min)
|
||||
should.equal(int32.overflow(int32.add(int1, int2)), expected)
|
||||
}
|
||||
|
||||
pub fn eject_test() {
|
||||
let assert Ok(int1) = int32.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
should.equal(int32.eject(int32.add(int1, int2)), bigi.from_int(max + 1))
|
||||
}
|
104
test/builtin/int64_test.gleam
Normal file
104
test/builtin/int64_test.gleam
Normal file
|
@ -0,0 +1,104 @@
|
|||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/int64
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
pub fn absolute_test() {
|
||||
let assert Ok(int) = int64.from_bigint(bigi.from_int(-1))
|
||||
should.equal(int64.absolute(int), int64.from_bigint(bigi.from_int(1)))
|
||||
}
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(int1) = int64.from_bigint(bigi.from_int(-1))
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(int64.add(int1, int2), int64.from_bigint(bigi.from_int(0)))
|
||||
}
|
||||
|
||||
pub fn subtract_test() {
|
||||
let assert Ok(int1) = int64.from_bigint(bigi.from_int(-1))
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(int64.subtract(int1, int2), int64.from_bigint(bigi.from_int(-2)))
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let assert Ok(int1) = int64.from_bigint(bigi.from_int(2))
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(int64.multiply(int1, int2), int64.from_bigint(bigi.from_int(4)))
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let assert Ok(int1) = int64.from_bigint(bigi.from_int(-2))
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int64.divide(int1, int2), int64.from_bigint(bigi.from_int(1)))
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let assert Ok(int1) = int64.from_bigint(bigi.from_int(2))
|
||||
should.be_error(int64.divide_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int64.divide_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int64.from_bigint(bigi.from_int(1))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let assert Ok(int1) = int64.from_bigint(bigi.from_int(-2))
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int64.modulo(int1, int2), int64.from_bigint(bigi.from_int(0)))
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let assert Ok(int1) = int64.from_bigint(bigi.from_int(2))
|
||||
should.be_error(int64.modulo_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int64.modulo_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int64.from_bigint(bigi.from_int(0))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let assert Ok(int1) = int64.from_bigint(bigi.from_int(-2))
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int64.remainder(int1, int2), int64.from_bigint(bigi.from_int(0)))
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let assert Ok(int1) = int64.from_bigint(bigi.from_int(2))
|
||||
should.be_error(int64.remainder_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int64.remainder_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int64.from_bigint(bigi.from_int(0))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let assert Ok(int1) = int64.from_bigint(bigi.from_int(-2))
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
should.equal(int64.power(int1, int2), int64.from_bigint(bigi.from_int(4)))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let #(min, max) = minmax()
|
||||
let assert Ok(int1) = int64.from_bigint(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(expected) = int64.from_bigint(min)
|
||||
should.equal(int64.overflow(int64.add(int1, int2)), expected)
|
||||
}
|
||||
|
||||
pub fn eject_test() {
|
||||
let #(_min, max) = minmax()
|
||||
let assert Ok(int1) = int64.from_bigint(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
should.equal(
|
||||
int64.eject(int64.add(int1, int2)),
|
||||
bigi.add(max, bigi.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
fn minmax() {
|
||||
let assert Ok(b63) = bigi.power(bigi.from_int(2), bigi.from_int(63))
|
||||
let min = bigi.multiply(b63, bigi.from_int(-1))
|
||||
let max = bigi.subtract(bigi.absolute(min), bigi.from_int(1))
|
||||
|
||||
#(min, max)
|
||||
}
|
95
test/builtin/int8_test.gleam
Normal file
95
test/builtin/int8_test.gleam
Normal file
|
@ -0,0 +1,95 @@
|
|||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/int8
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const min = -128
|
||||
|
||||
const max = 127
|
||||
|
||||
pub fn absolute_test() {
|
||||
let assert Ok(int) = int8.from_int(-1)
|
||||
should.equal(int8.absolute(int), int8.from_int(1))
|
||||
}
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(int1) = int8.from_int(-1)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(int8.add(int1, int2), int8.from_int(0))
|
||||
}
|
||||
|
||||
pub fn subtract_test() {
|
||||
let assert Ok(int1) = int8.from_int(-1)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(int8.subtract(int1, int2), int8.from_int(-2))
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let assert Ok(int1) = int8.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(int8.multiply(int1, int2), int8.from_int(4))
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let assert Ok(int1) = int8.from_int(-2)
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int8.divide(int1, int2), int8.from_int(1))
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let assert Ok(int1) = int8.from_int(2)
|
||||
should.be_error(int8.divide_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int8.divide_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int8.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let assert Ok(int1) = int8.from_int(-2)
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int8.modulo(int1, int2), int8.from_int(0))
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let assert Ok(int1) = int8.from_int(2)
|
||||
should.be_error(int8.modulo_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int8.modulo_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int8.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let assert Ok(int1) = int8.from_int(-2)
|
||||
let assert int2 = bigi.from_int(-2)
|
||||
should.equal(int8.remainder(int1, int2), int8.from_int(0))
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let assert Ok(int1) = int8.from_int(2)
|
||||
should.be_error(int8.remainder_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
int8.remainder_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(int8.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let assert Ok(int1) = int8.from_int(-2)
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
should.equal(int8.power(int1, int2), int8.from_int(4))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let assert Ok(int1) = int8.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(expected) = int8.from_int(min)
|
||||
should.equal(int8.overflow(int8.add(int1, int2)), expected)
|
||||
}
|
||||
|
||||
pub fn eject_test() {
|
||||
let assert Ok(int1) = int8.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
should.equal(int8.eject(int8.add(int1, int2)), bigi.from_int(max + 1))
|
||||
}
|
114
test/builtin/uint128_test.gleam
Normal file
114
test/builtin/uint128_test.gleam
Normal file
|
@ -0,0 +1,114 @@
|
|||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/uint128
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(int1) = uint128.from_bigint(bigi.from_int(0))
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(uint128.add(int1, int2), uint128.from_bigint(bigi.from_int(1)))
|
||||
}
|
||||
|
||||
pub fn subtract_test() {
|
||||
let assert Ok(int1) = uint128.from_bigint(bigi.from_int(1))
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(
|
||||
uint128.subtract(int1, int2),
|
||||
uint128.from_bigint(bigi.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let assert Ok(int1) = uint128.from_bigint(bigi.from_int(2))
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(
|
||||
uint128.multiply(int1, int2),
|
||||
uint128.from_bigint(bigi.from_int(4)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let assert Ok(int1) = uint128.from_bigint(bigi.from_int(2))
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(
|
||||
uint128.divide(int1, int2),
|
||||
uint128.from_bigint(bigi.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let assert Ok(int1) = uint128.from_bigint(bigi.from_int(2))
|
||||
should.be_error(uint128.divide_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint128.divide_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint128.from_bigint(bigi.from_int(1))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let assert Ok(int1) = uint128.from_bigint(bigi.from_int(2))
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(
|
||||
uint128.modulo(int1, int2),
|
||||
uint128.from_bigint(bigi.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let assert Ok(int1) = uint128.from_bigint(bigi.from_int(2))
|
||||
should.be_error(uint128.modulo_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint128.modulo_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint128.from_bigint(bigi.from_int(0))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let assert Ok(int1) = uint128.from_bigint(bigi.from_int(2))
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(
|
||||
uint128.remainder(int1, int2),
|
||||
uint128.from_bigint(bigi.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let assert Ok(int1) = uint128.from_bigint(bigi.from_int(2))
|
||||
should.be_error(uint128.remainder_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint128.remainder_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint128.from_bigint(bigi.from_int(0))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let assert Ok(int1) = uint128.from_bigint(bigi.from_int(2))
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
should.equal(uint128.power(int1, int2), uint128.from_bigint(bigi.from_int(4)))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let #(min, max) = minmax()
|
||||
let assert Ok(int1) = uint128.from_bigint(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(expected) = uint128.from_bigint(min)
|
||||
should.equal(uint128.overflow(uint128.add(int1, int2)), expected)
|
||||
}
|
||||
|
||||
pub fn eject_test() {
|
||||
let #(_min, max) = minmax()
|
||||
let assert Ok(int1) = uint128.from_bigint(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
should.equal(
|
||||
uint128.eject(uint128.add(int1, int2)),
|
||||
bigi.add(max, bigi.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
fn minmax() {
|
||||
let assert Ok(b128) = bigi.power(bigi.from_int(2), bigi.from_int(128))
|
||||
let min = bigi.zero()
|
||||
let max = bigi.subtract(b128, bigi.from_int(1))
|
||||
|
||||
#(min, max)
|
||||
}
|
|
@ -1,10 +1,90 @@
|
|||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/uint16
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const min = 0
|
||||
|
||||
const max = 65_535
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(a) = uint16.from_bigint(bigi.zero())
|
||||
let b = bigi.from_int(12)
|
||||
let c = uint16.eject(uint16.add(a, b))
|
||||
should.equal(c, bigi.from_int(12))
|
||||
let assert Ok(int1) = uint16.from_int(0)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(uint16.add(int1, int2), uint16.from_int(1))
|
||||
}
|
||||
|
||||
pub fn subtract_test() {
|
||||
let assert Ok(int1) = uint16.from_int(1)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(uint16.subtract(int1, int2), uint16.from_int(0))
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let assert Ok(int1) = uint16.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint16.multiply(int1, int2), uint16.from_int(4))
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let assert Ok(int1) = uint16.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint16.divide(int1, int2), uint16.from_int(1))
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let assert Ok(int1) = uint16.from_int(2)
|
||||
should.be_error(uint16.divide_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint16.divide_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint16.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let assert Ok(int1) = uint16.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint16.modulo(int1, int2), uint16.from_int(0))
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let assert Ok(int1) = uint16.from_int(2)
|
||||
should.be_error(uint16.modulo_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint16.modulo_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint16.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let assert Ok(int1) = uint16.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint16.remainder(int1, int2), uint16.from_int(0))
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let assert Ok(int1) = uint16.from_int(2)
|
||||
should.be_error(uint16.remainder_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint16.remainder_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint16.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let assert Ok(int1) = uint16.from_int(2)
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
should.equal(uint16.power(int1, int2), uint16.from_int(4))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let assert Ok(int1) = uint16.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(expected) = uint16.from_int(min)
|
||||
should.equal(uint16.overflow(uint16.add(int1, int2)), expected)
|
||||
}
|
||||
|
||||
pub fn eject_test() {
|
||||
let assert Ok(int1) = uint16.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
should.equal(uint16.eject(uint16.add(int1, int2)), bigi.from_int(max + 1))
|
||||
}
|
||||
|
|
90
test/builtin/uint32_test.gleam
Normal file
90
test/builtin/uint32_test.gleam
Normal file
|
@ -0,0 +1,90 @@
|
|||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/uint32
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const min = 0
|
||||
|
||||
const max = 4_294_967_295
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(int1) = uint32.from_int(0)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(uint32.add(int1, int2), uint32.from_int(1))
|
||||
}
|
||||
|
||||
pub fn subtract_test() {
|
||||
let assert Ok(int1) = uint32.from_int(1)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(uint32.subtract(int1, int2), uint32.from_int(0))
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let assert Ok(int1) = uint32.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint32.multiply(int1, int2), uint32.from_int(4))
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let assert Ok(int1) = uint32.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint32.divide(int1, int2), uint32.from_int(1))
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let assert Ok(int1) = uint32.from_int(2)
|
||||
should.be_error(uint32.divide_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint32.divide_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint32.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let assert Ok(int1) = uint32.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint32.modulo(int1, int2), uint32.from_int(0))
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let assert Ok(int1) = uint32.from_int(2)
|
||||
should.be_error(uint32.modulo_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint32.modulo_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint32.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let assert Ok(int1) = uint32.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint32.remainder(int1, int2), uint32.from_int(0))
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let assert Ok(int1) = uint32.from_int(2)
|
||||
should.be_error(uint32.remainder_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint32.remainder_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint32.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let assert Ok(int1) = uint32.from_int(2)
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
should.equal(uint32.power(int1, int2), uint32.from_int(4))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let assert Ok(int1) = uint32.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(expected) = uint32.from_int(min)
|
||||
should.equal(uint32.overflow(uint32.add(int1, int2)), expected)
|
||||
}
|
||||
|
||||
pub fn eject_test() {
|
||||
let assert Ok(int1) = uint32.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
should.equal(uint32.eject(uint32.add(int1, int2)), bigi.from_int(max + 1))
|
||||
}
|
108
test/builtin/uint64_test.gleam
Normal file
108
test/builtin/uint64_test.gleam
Normal file
|
@ -0,0 +1,108 @@
|
|||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/uint64
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(int1) = uint64.from_bigint(bigi.from_int(0))
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(uint64.add(int1, int2), uint64.from_bigint(bigi.from_int(1)))
|
||||
}
|
||||
|
||||
pub fn subtract_test() {
|
||||
let assert Ok(int1) = uint64.from_bigint(bigi.from_int(1))
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(
|
||||
uint64.subtract(int1, int2),
|
||||
uint64.from_bigint(bigi.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let assert Ok(int1) = uint64.from_bigint(bigi.from_int(2))
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(
|
||||
uint64.multiply(int1, int2),
|
||||
uint64.from_bigint(bigi.from_int(4)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let assert Ok(int1) = uint64.from_bigint(bigi.from_int(2))
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint64.divide(int1, int2), uint64.from_bigint(bigi.from_int(1)))
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let assert Ok(int1) = uint64.from_bigint(bigi.from_int(2))
|
||||
should.be_error(uint64.divide_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint64.divide_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint64.from_bigint(bigi.from_int(1))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let assert Ok(int1) = uint64.from_bigint(bigi.from_int(2))
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint64.modulo(int1, int2), uint64.from_bigint(bigi.from_int(0)))
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let assert Ok(int1) = uint64.from_bigint(bigi.from_int(2))
|
||||
should.be_error(uint64.modulo_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint64.modulo_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint64.from_bigint(bigi.from_int(0))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let assert Ok(int1) = uint64.from_bigint(bigi.from_int(2))
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(
|
||||
uint64.remainder(int1, int2),
|
||||
uint64.from_bigint(bigi.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let assert Ok(int1) = uint64.from_bigint(bigi.from_int(2))
|
||||
should.be_error(uint64.remainder_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint64.remainder_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint64.from_bigint(bigi.from_int(0))),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let assert Ok(int1) = uint64.from_bigint(bigi.from_int(2))
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
should.equal(uint64.power(int1, int2), uint64.from_bigint(bigi.from_int(4)))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let #(min, max) = minmax()
|
||||
let assert Ok(int1) = uint64.from_bigint(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(expected) = uint64.from_bigint(min)
|
||||
should.equal(uint64.overflow(uint64.add(int1, int2)), expected)
|
||||
}
|
||||
|
||||
pub fn eject_test() {
|
||||
let #(_min, max) = minmax()
|
||||
let assert Ok(int1) = uint64.from_bigint(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
should.equal(
|
||||
uint64.eject(uint64.add(int1, int2)),
|
||||
bigi.add(max, bigi.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
fn minmax() {
|
||||
let assert Ok(b64) = bigi.power(bigi.from_int(2), bigi.from_int(64))
|
||||
let min = bigi.zero()
|
||||
let max = bigi.subtract(b64, bigi.from_int(1))
|
||||
|
||||
#(min, max)
|
||||
}
|
|
@ -1,31 +1,90 @@
|
|||
import bigi
|
||||
import gleeunit/should
|
||||
import ranged_int/builtin/uint8
|
||||
import ranged_int/builtin/uint
|
||||
|
||||
const min = 0
|
||||
|
||||
const max = 255
|
||||
|
||||
pub fn add_test() {
|
||||
let assert Ok(a) = uint8.from_bigint(bigi.zero())
|
||||
let b = bigi.from_int(12)
|
||||
let c = uint8.eject(uint8.add(a, b))
|
||||
should.equal(c, bigi.from_int(12))
|
||||
let assert Ok(int1) = uint8.from_int(0)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(uint8.add(int1, int2), uint8.from_int(1))
|
||||
}
|
||||
|
||||
pub fn subtract_test() {
|
||||
let assert Ok(int1) = uint8.from_int(1)
|
||||
let assert int2 = bigi.from_int(1)
|
||||
should.equal(uint8.subtract(int1, int2), uint8.from_int(0))
|
||||
}
|
||||
|
||||
pub fn multiply_test() {
|
||||
let assert Ok(int1) = uint8.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint8.multiply(int1, int2), uint8.from_int(4))
|
||||
}
|
||||
|
||||
pub fn divide_test() {
|
||||
let assert Ok(a) = uint8.from_int(120)
|
||||
let b = bigi.from_int(12)
|
||||
let assert Ok(c) = uint8.divide_no_zero(a, b)
|
||||
should.equal(uint8.eject(c), bigi.from_int(10))
|
||||
let assert Ok(int1) = uint8.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint8.divide(int1, int2), uint8.from_int(1))
|
||||
}
|
||||
|
||||
pub fn divide_no_zero_test() {
|
||||
let assert Ok(int1) = uint8.from_int(2)
|
||||
should.be_error(uint8.divide_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint8.divide_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint8.from_int(1)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn modulo_test() {
|
||||
let assert Ok(int1) = uint8.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint8.modulo(int1, int2), uint8.from_int(0))
|
||||
}
|
||||
|
||||
pub fn modulo_no_zero_test() {
|
||||
let assert Ok(int1) = uint8.from_int(2)
|
||||
should.be_error(uint8.modulo_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint8.modulo_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint8.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remainder_test() {
|
||||
let assert Ok(int1) = uint8.from_int(2)
|
||||
let assert int2 = bigi.from_int(2)
|
||||
should.equal(uint8.remainder(int1, int2), uint8.from_int(0))
|
||||
}
|
||||
|
||||
pub fn remainder_no_zero_test() {
|
||||
let assert Ok(int1) = uint8.from_int(2)
|
||||
should.be_error(uint8.remainder_no_zero(int1, bigi.zero()))
|
||||
should.equal(
|
||||
uint8.remainder_no_zero(int1, bigi.from_int(2)),
|
||||
Ok(uint8.from_int(0)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn power_test() {
|
||||
let assert Ok(int1) = uint8.from_int(2)
|
||||
let assert Ok(int2) = uint.from_bigint(bigi.from_int(2))
|
||||
should.equal(uint8.power(int1, int2), uint8.from_int(4))
|
||||
}
|
||||
|
||||
pub fn overflow_test() {
|
||||
let assert Ok(a) = uint8.from_int(120)
|
||||
let b = bigi.from_int(160)
|
||||
let c = uint8.overflow(uint8.add(a, b))
|
||||
should.equal(uint8.to_int(c), 24)
|
||||
let assert Ok(int1) = uint8.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
let assert Ok(expected) = uint8.from_int(min)
|
||||
should.equal(uint8.overflow(uint8.add(int1, int2)), expected)
|
||||
}
|
||||
|
||||
pub fn underflow_test() {
|
||||
let assert Ok(a) = uint8.from_bigint(bigi.from_int(120))
|
||||
let b = bigi.from_int(160)
|
||||
let c = uint8.overflow(uint8.subtract(a, b))
|
||||
should.equal(uint8.to_bigint(c), bigi.from_int(216))
|
||||
pub fn eject_test() {
|
||||
let assert Ok(int1) = uint8.from_int(max)
|
||||
let int2 = bigi.from_int(1)
|
||||
should.equal(uint8.eject(uint8.add(int1, int2)), bigi.from_int(max + 1))
|
||||
}
|
||||
|
|
484
test/overflow_test.gleam
Normal file
484
test/overflow_test.gleam
Normal file
|
@ -0,0 +1,484 @@
|
|||
import gleam/list
|
||||
import gleeunit/should
|
||||
import bigi
|
||||
import ranged_int/utils
|
||||
|
||||
const uint8_testset = [
|
||||
#(112, 225, 81),
|
||||
#(228, 195, 167),
|
||||
#(179, 142, 65),
|
||||
#(232, 68, 44),
|
||||
#(220, 94, 58),
|
||||
#(110, 147, 1),
|
||||
#(103, 196, 43),
|
||||
#(204, 212, 160),
|
||||
#(109, 211, 64),
|
||||
#(239, 57, 40),
|
||||
#(137, 146, 27),
|
||||
#(213, 62, 19),
|
||||
#(110, 205, 59),
|
||||
#(172, 131, 47),
|
||||
#(97, 190, 31),
|
||||
#(137, 203, 84),
|
||||
#(249, 209, 202),
|
||||
#(202, 107, 53),
|
||||
#(158, 159, 61),
|
||||
#(204, 253, 201),
|
||||
#(184, 176, 104),
|
||||
#(166, 221, 131),
|
||||
#(209, 226, 179),
|
||||
#(231, 117, 92),
|
||||
#(171, 157, 72),
|
||||
#(147, 229, 120),
|
||||
#(239, 104, 87),
|
||||
#(221, 112, 77),
|
||||
#(240, 116, 100),
|
||||
#(166, 247, 157),
|
||||
#(198, 98, 40),
|
||||
#(192, 229, 165),
|
||||
#(200, 60, 4),
|
||||
#(180, 85, 9),
|
||||
#(171, 222, 137),
|
||||
#(210, 57, 11),
|
||||
#(86, 208, 38),
|
||||
#(74, 236, 54),
|
||||
#(206, 241, 191),
|
||||
#(164, 100, 8),
|
||||
#(244, 246, 234),
|
||||
#(143, 246, 133),
|
||||
#(131, 142, 17),
|
||||
#(118, 194, 56),
|
||||
#(31, 229, 4),
|
||||
#(185, 145, 74),
|
||||
#(121, 181, 46),
|
||||
#(195, 190, 129),
|
||||
#(248, 103, 95),
|
||||
#(195, 125, 64),
|
||||
#(143, 228, 115),
|
||||
#(99, 182, 25),
|
||||
#(171, 103, 18),
|
||||
#(212, 107, 63),
|
||||
#(48, 252, 44),
|
||||
#(135, 157, 36),
|
||||
#(104, 199, 47),
|
||||
#(252, 136, 132),
|
||||
#(219, 194, 157),
|
||||
#(182, 95, 21),
|
||||
#(110, 171, 25),
|
||||
#(135, 244, 123),
|
||||
#(56, 213, 13),
|
||||
#(7, 251, 2),
|
||||
#(53, 227, 24),
|
||||
#(226, 194, 164),
|
||||
#(150, 197, 91),
|
||||
#(116, 181, 41),
|
||||
#(89, 199, 32),
|
||||
#(97, 234, 75),
|
||||
#(114, 212, 70),
|
||||
#(219, 197, 160),
|
||||
#(232, 211, 187),
|
||||
#(215, 236, 195),
|
||||
#(153, 143, 40),
|
||||
#(144, 225, 113),
|
||||
#(134, 214, 92),
|
||||
#(181, 179, 104),
|
||||
#(105, 187, 36),
|
||||
#(12, 247, 3),
|
||||
#(250, 23, 17),
|
||||
#(237, 89, 70),
|
||||
#(233, 224, 201),
|
||||
#(210, 236, 190),
|
||||
#(233, 208, 185),
|
||||
#(132, 172, 48),
|
||||
#(197, 244, 185),
|
||||
#(194, 143, 81),
|
||||
#(232, 59, 35),
|
||||
#(61, 214, 19),
|
||||
#(224, 105, 73),
|
||||
#(208, 62, 14),
|
||||
#(165, 191, 100),
|
||||
#(253, 245, 242),
|
||||
#(142, 201, 87),
|
||||
#(220, 55, 19),
|
||||
#(249, 195, 188),
|
||||
#(57, 230, 31),
|
||||
#(192, 250, 186),
|
||||
#(248, 132, 124),
|
||||
]
|
||||
|
||||
const uint16_testset = [
|
||||
#(53_507, 23_855, 11_826),
|
||||
#(46_924, 25_977, 7365),
|
||||
#(65_063, 53_609, 53_136),
|
||||
#(57_356, 40_806, 32_626),
|
||||
#(57_039, 42_996, 34_499),
|
||||
#(52_094, 44_757, 31_315),
|
||||
#(51_826, 58_047, 44_337),
|
||||
#(34_558, 36_127, 5149),
|
||||
#(46_715, 50_409, 31_588),
|
||||
#(47_464, 37_618, 19_546),
|
||||
#(5454, 61_708, 1626),
|
||||
#(58_546, 38_113, 31_123),
|
||||
#(42_084, 32_688, 9236),
|
||||
#(41_435, 25_026, 925),
|
||||
#(30_086, 54_929, 19_479),
|
||||
#(23_497, 52_484, 10_445),
|
||||
#(53_057, 27_358, 14_879),
|
||||
#(39_282, 27_525, 1271),
|
||||
#(14_626, 63_958, 13_048),
|
||||
#(22_728, 54_372, 11_564),
|
||||
#(45_820, 22_584, 2868),
|
||||
#(43_481, 47_301, 25_246),
|
||||
#(60_280, 43_875, 38_619),
|
||||
#(46_998, 64_467, 45_929),
|
||||
#(64_531, 3171, 2166),
|
||||
#(22_327, 45_778, 2569),
|
||||
#(44_104, 57_573, 36_141),
|
||||
#(53_933, 21_452, 9849),
|
||||
#(28_246, 64_724, 27_434),
|
||||
#(63_087, 61_533, 59_084),
|
||||
#(62_571, 23_304, 20_339),
|
||||
#(51_536, 21_086, 7086),
|
||||
#(45_994, 54_043, 34_501),
|
||||
#(20_775, 64_334, 19_573),
|
||||
#(41_124, 42_995, 18_583),
|
||||
#(65_170, 11_754, 11_388),
|
||||
#(9262, 62_579, 6305),
|
||||
#(50_708, 26_924, 12_096),
|
||||
#(48_199, 55_200, 37_863),
|
||||
#(60_936, 43_822, 39_222),
|
||||
#(60_862, 47_890, 43_216),
|
||||
#(50_526, 36_306, 21_296),
|
||||
#(24_522, 48_247, 7233),
|
||||
#(45_165, 28_277, 7906),
|
||||
#(48_854, 42_715, 26_033),
|
||||
#(18_201, 47_541, 206),
|
||||
#(48_568, 25_429, 8461),
|
||||
#(57_765, 30_968, 23_197),
|
||||
#(56_158, 38_031, 28_653),
|
||||
#(22_481, 60_589, 17_534),
|
||||
#(60_561, 35_159, 30_184),
|
||||
#(60_390, 46_931, 41_785),
|
||||
#(42_584, 51_757, 28_805),
|
||||
#(50_536, 16_272, 1272),
|
||||
#(47_834, 27_980, 10_278),
|
||||
#(54_982, 15_731, 5177),
|
||||
#(30_296, 42_947, 7707),
|
||||
#(36_689, 63_208, 34_361),
|
||||
#(32_499, 62_076, 29_039),
|
||||
#(65_165, 31_455, 31_084),
|
||||
#(58_090, 20_060, 12_614),
|
||||
#(53_436, 29_679, 17_579),
|
||||
#(41_189, 44_383, 20_036),
|
||||
#(36_593, 52_979, 24_036),
|
||||
#(39_633, 61_750, 35_847),
|
||||
#(35_551, 33_517, 3532),
|
||||
#(20_920, 63_223, 18_607),
|
||||
#(58_628, 40_720, 33_812),
|
||||
#(18_784, 60_975, 14_223),
|
||||
#(52_625, 21_870, 8959),
|
||||
#(28_227, 63_187, 25_878),
|
||||
#(30_310, 50_085, 14_859),
|
||||
#(49_863, 42_716, 27_043),
|
||||
#(62_185, 54_112, 50_761),
|
||||
#(43_652, 33_395, 11_511),
|
||||
#(56_274, 22_812, 13_550),
|
||||
#(36_147, 49_560, 20_171),
|
||||
#(57_354, 14_989, 6807),
|
||||
#(54_674, 24_884, 14_022),
|
||||
#(53_699, 50_088, 38_251),
|
||||
#(38_902, 37_979, 11_345),
|
||||
#(62_742, 64_319, 61_525),
|
||||
#(54_841, 12_958, 2263),
|
||||
#(7886, 63_011, 5361),
|
||||
#(58_935, 21_019, 14_418),
|
||||
#(47_831, 26_851, 9146),
|
||||
#(45_962, 39_335, 19_761),
|
||||
#(53_975, 11_981, 420),
|
||||
#(26_477, 58_093, 19_034),
|
||||
#(44_588, 53_937, 32_989),
|
||||
#(61_810, 49_637, 45_911),
|
||||
#(19_980, 62_256, 16_700),
|
||||
#(64_110, 17_762, 16_336),
|
||||
#(4497, 61_449, 410),
|
||||
#(40_318, 38_443, 13_225),
|
||||
#(62_311, 39_529, 36_304),
|
||||
#(18_039, 64_797, 17_300),
|
||||
#(18_179, 52_010, 4653),
|
||||
#(52_719, 26_144, 13_327),
|
||||
#(48_750, 32_082, 15_296),
|
||||
]
|
||||
|
||||
const int8_multiply_testset = [
|
||||
#(87, 66, 110),
|
||||
#(47, 34, 62),
|
||||
#(-12, -81, -52),
|
||||
#(76, 75, 68),
|
||||
#(-16, -74, -96),
|
||||
#(-66, -59, 54),
|
||||
#(46, 48, -96),
|
||||
#(-73, -118, -90),
|
||||
#(120, 8, -64),
|
||||
#(68, 120, -32),
|
||||
#(92, 87, 68),
|
||||
#(-47, -85, -101),
|
||||
#(74, 72, -48),
|
||||
#(-127, -43, 85),
|
||||
#(97, 108, -20),
|
||||
#(37, 12, -68),
|
||||
#(120, 67, 104),
|
||||
#(97, 19, 51),
|
||||
#(-62, -96, 64),
|
||||
#(-99, -84, 124),
|
||||
#(-14, -103, -94),
|
||||
#(106, 66, 84),
|
||||
#(-21, -49, 5),
|
||||
#(40, 73, 104),
|
||||
#(61, 91, -81),
|
||||
#(-5, -81, -107),
|
||||
#(-69, -22, -18),
|
||||
#(11, 35, -127),
|
||||
#(-112, -14, 32),
|
||||
#(-15, -90, 70),
|
||||
#(53, 3, -97),
|
||||
#(126, 88, 80),
|
||||
#(38, 32, -64),
|
||||
#(-114, -65, -14),
|
||||
#(31, 71, -103),
|
||||
#(8, 35, 24),
|
||||
#(34, 96, -64),
|
||||
#(23, 103, 65),
|
||||
#(-32, -102, -64),
|
||||
#(112, 87, 16),
|
||||
#(-45, -15, -93),
|
||||
#(75, 15, 101),
|
||||
#(-32, -106, 64),
|
||||
#(11, 109, -81),
|
||||
#(99, 30, -102),
|
||||
#(88, 51, -120),
|
||||
#(-38, -112, -96),
|
||||
#(78, 107, -102),
|
||||
#(52, 55, 44),
|
||||
#(96, 103, -96),
|
||||
#(-55, -110, -94),
|
||||
#(42, 42, -28),
|
||||
#(-109, -83, 87),
|
||||
#(117, 124, -84),
|
||||
#(49, 108, -84),
|
||||
#(17, 93, 45),
|
||||
#(-75, -81, -69),
|
||||
#(122, 115, -50),
|
||||
#(-91, -33, -69),
|
||||
#(113, 74, -86),
|
||||
#(-99, -44, 4),
|
||||
#(-10, -73, -38),
|
||||
#(-75, -104, 120),
|
||||
#(18, 59, 38),
|
||||
#(-77, -18, 106),
|
||||
#(-95, -6, 58),
|
||||
#(-125, -37, 17),
|
||||
#(-99, -42, 62),
|
||||
#(118, 110, -76),
|
||||
#(-22, -53, -114),
|
||||
#(-89, -128, -128),
|
||||
#(101, 57, 125),
|
||||
#(100, 79, -36),
|
||||
#(18, 32, 64),
|
||||
#(-19, -12, -28),
|
||||
#(90, 120, 48),
|
||||
#(57, 20, 116),
|
||||
#(-47, -85, -101),
|
||||
#(-69, -102, 126),
|
||||
#(62, 23, -110),
|
||||
#(116, 34, 104),
|
||||
#(105, 32, 32),
|
||||
#(-22, -7, -102),
|
||||
#(-70, -68, -104),
|
||||
#(-10, -42, -92),
|
||||
#(-5, -75, 119),
|
||||
#(115, 42, -34),
|
||||
#(-85, -9, -3),
|
||||
#(-80, -11, 112),
|
||||
#(76, 51, 36),
|
||||
#(106, 5, 18),
|
||||
#(117, 27, 87),
|
||||
#(10, 113, 106),
|
||||
#(-40, -116, 32),
|
||||
#(-43, -6, 2),
|
||||
#(97, 105, -55),
|
||||
#(-12, -65, 12),
|
||||
#(-55, -118, 90),
|
||||
#(-46, -55, -30),
|
||||
#(70, 93, 110),
|
||||
]
|
||||
|
||||
const int8_underflow_testset = [
|
||||
#(-57, 92, 107),
|
||||
#(-123, 11, 122),
|
||||
#(-115, 48, 93),
|
||||
#(-128, 52, 76),
|
||||
#(-125, 105, 26),
|
||||
#(-76, 78, 102),
|
||||
#(-76, 92, 88),
|
||||
#(-46, 101, 109),
|
||||
#(-110, 80, 66),
|
||||
#(-62, 80, 114),
|
||||
#(-75, 77, 104),
|
||||
#(-127, 54, 75),
|
||||
#(-121, 121, 14),
|
||||
#(-127, 3, 126),
|
||||
#(-72, 68, 116),
|
||||
#(-93, 83, 80),
|
||||
#(-110, 112, 34),
|
||||
#(-83, 59, 114),
|
||||
#(-124, 109, 23),
|
||||
#(-121, 81, 54),
|
||||
#(-72, 105, 79),
|
||||
#(-106, 104, 46),
|
||||
#(-122, 78, 56),
|
||||
#(-99, 40, 117),
|
||||
#(-88, 83, 85),
|
||||
#(-68, 97, 91),
|
||||
#(-106, 93, 57),
|
||||
#(-94, 57, 105),
|
||||
#(-78, 125, 53),
|
||||
#(-122, 71, 63),
|
||||
#(-80, 97, 79),
|
||||
#(-118, 51, 87),
|
||||
#(-83, 79, 94),
|
||||
#(-122, 100, 34),
|
||||
#(-102, 49, 105),
|
||||
#(-84, 87, 85),
|
||||
#(-56, 111, 89),
|
||||
#(-82, 56, 118),
|
||||
#(-111, 58, 87),
|
||||
#(-117, 29, 110),
|
||||
#(-112, 57, 87),
|
||||
#(-115, 34, 107),
|
||||
#(-92, 100, 64),
|
||||
#(-107, 99, 50),
|
||||
#(-49, 124, 83),
|
||||
#(-125, 104, 27),
|
||||
#(-116, 122, 18),
|
||||
#(-116, 121, 19),
|
||||
#(-128, 74, 54),
|
||||
#(-34, 102, 120),
|
||||
#(-126, 56, 74),
|
||||
#(-63, 68, 125),
|
||||
#(-13, 116, 127),
|
||||
#(-82, 59, 115),
|
||||
#(-99, 84, 73),
|
||||
#(-65, 77, 114),
|
||||
#(-128, 113, 15),
|
||||
#(-100, 124, 32),
|
||||
#(-63, 104, 89),
|
||||
#(-120, 53, 83),
|
||||
#(-80, 86, 90),
|
||||
#(-36, 101, 119),
|
||||
#(-78, 97, 81),
|
||||
#(-80, 74, 102),
|
||||
#(-52, 105, 99),
|
||||
#(-76, 104, 76),
|
||||
#(-121, 110, 25),
|
||||
#(-102, 35, 119),
|
||||
#(-35, 122, 99),
|
||||
#(-118, 100, 38),
|
||||
#(-82, 111, 63),
|
||||
#(-18, 115, 123),
|
||||
#(-81, 105, 70),
|
||||
#(-113, 79, 64),
|
||||
#(-49, 104, 103),
|
||||
#(-44, 94, 118),
|
||||
#(-46, 85, 125),
|
||||
#(-51, 81, 124),
|
||||
#(-50, 115, 91),
|
||||
#(-50, 105, 101),
|
||||
#(-49, 123, 84),
|
||||
#(-97, 91, 68),
|
||||
#(-89, 67, 100),
|
||||
#(-93, 85, 78),
|
||||
#(-91, 91, 74),
|
||||
#(-102, 38, 116),
|
||||
#(-116, 17, 123),
|
||||
#(-23, 110, 123),
|
||||
#(-45, 95, 116),
|
||||
#(-65, 82, 109),
|
||||
#(-126, 85, 45),
|
||||
#(-33, 123, 100),
|
||||
#(-68, 113, 75),
|
||||
#(-80, 104, 72),
|
||||
#(-127, 49, 80),
|
||||
#(-108, 112, 36),
|
||||
#(-123, 114, 19),
|
||||
#(-76, 75, 105),
|
||||
#(-82, 70, 104),
|
||||
#(-114, 76, 66),
|
||||
]
|
||||
|
||||
pub fn uint8_overflow_test() {
|
||||
list.each(uint8_testset, fn(data) {
|
||||
let a = bigi.from_int(data.0)
|
||||
let b = bigi.from_int(data.1)
|
||||
let c = bigi.add(a, b)
|
||||
let d = bigi.subtract(c, bigi.from_int(255))
|
||||
should.equal(
|
||||
utils.overflow(
|
||||
utils.WouldOverflow(d),
|
||||
min: bigi.zero(),
|
||||
max: bigi.from_int(255),
|
||||
),
|
||||
bigi.from_int(data.2),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn uint16_overflow_test() {
|
||||
list.each(uint16_testset, fn(data) {
|
||||
let a = bigi.from_int(data.0)
|
||||
let b = bigi.from_int(data.1)
|
||||
let c = bigi.add(a, b)
|
||||
let d = bigi.subtract(c, bigi.from_int(65_535))
|
||||
should.equal(
|
||||
utils.overflow(
|
||||
utils.WouldOverflow(d),
|
||||
min: bigi.zero(),
|
||||
max: bigi.from_int(65_535),
|
||||
),
|
||||
bigi.from_int(data.2),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn int8_overflow_test() {
|
||||
list.each(int8_multiply_testset, fn(data) {
|
||||
let a = bigi.from_int(data.0)
|
||||
let b = bigi.from_int(data.1)
|
||||
let c = bigi.multiply(a, b)
|
||||
let d = bigi.subtract(c, bigi.from_int(127))
|
||||
should.equal(
|
||||
utils.overflow(
|
||||
utils.WouldOverflow(d),
|
||||
min: bigi.from_int(-128),
|
||||
max: bigi.from_int(127),
|
||||
),
|
||||
bigi.from_int(data.2),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn int8_underflow_test() {
|
||||
list.each(int8_underflow_testset, fn(data) {
|
||||
let a = bigi.from_int(data.0)
|
||||
let b = bigi.from_int(data.1)
|
||||
let c = bigi.subtract(a, b)
|
||||
let d = bigi.absolute(bigi.subtract(c, bigi.from_int(-128)))
|
||||
should.equal(
|
||||
utils.overflow(
|
||||
utils.WouldUnderflow(d),
|
||||
min: bigi.from_int(-128),
|
||||
max: bigi.from_int(127),
|
||||
),
|
||||
bigi.from_int(data.2),
|
||||
)
|
||||
})
|
||||
}
|
|
@ -41,3 +41,7 @@ pub fn from_bigint(value: BigInt) {
|
|||
pub fn compare(a: Katzen, b: Katzen) {
|
||||
interface.compare(a, b, iface)
|
||||
}
|
||||
|
||||
pub fn overflow(res: interface.OpResult(Katzen)) {
|
||||
interface.overflow(res, iface)
|
||||
}
|
||||
|
|
|
@ -15,5 +15,10 @@ pub fn mvp2_add_test() {
|
|||
let assert Ok(a) = mvp2.from_bigint(bigi.from_int(2007))
|
||||
let b = bigi.from_int(9)
|
||||
let c = mvp2.add(a, b)
|
||||
should.equal(c, Error(utils.DidOverflow(bigi.from_int(1))))
|
||||
should.equal(c, Error(utils.WouldOverflow(bigi.from_int(1))))
|
||||
should.equal(
|
||||
mvp2.overflow(c)
|
||||
|> mvp2.to_bigint(),
|
||||
bigi.from_int(2007),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -16,5 +16,5 @@ pub fn mvp_add_test() {
|
|||
let assert Ok(a) = interface.from_bigint(bigi.from_int(2007), mvp.iface)
|
||||
let b = bigi.from_int(9)
|
||||
let c = interface.math_op(a, b, mvp.iface, bigi.add)
|
||||
should.equal(c, Error(utils.DidOverflow(bigi.from_int(1))))
|
||||
should.equal(c, Error(utils.WouldOverflow(bigi.from_int(1))))
|
||||
}
|
||||
|
|
36
test/testgen/main.cc
Normal file
36
test/testgen/main.cc
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include <iostream>
|
||||
#include <random>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
const auto NUMS = 100;
|
||||
|
||||
int8_t generateRandomNumber(unsigned int numBits) {
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<int> dist(-128, 127);
|
||||
return dist(gen);
|
||||
}
|
||||
|
||||
int modulo(int a, int b) {
|
||||
const int result = a % b;
|
||||
return result >= 0 ? result : result + b;
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto numsSoFar = 0;
|
||||
while (numsSoFar < NUMS) {
|
||||
int8_t num1 = generateRandomNumber(8);
|
||||
int8_t num2 = generateRandomNumber(8);
|
||||
int32_t sum = num1 - num2;
|
||||
|
||||
if (sum < -128) {
|
||||
// Overflow occurred, adjust the sum
|
||||
int8_t over = sum;
|
||||
std::cout << "#(" << (int) num1 << ", " << (int) num2 << ", " << (int) over << ")," << std::endl;
|
||||
++numsSoFar;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue