Iterate iterate iterate

This commit is contained in:
Mikko Ahlroth 2024-02-10 12:29:31 +02:00
parent 3d3fe05372
commit c0e4dbc4ed
14 changed files with 406 additions and 164 deletions

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
pub opaque type Int128 {
Int128(data: BigInt)
@ -19,24 +19,44 @@ pub fn to_bigint(uint: Int128) {
uint.data
}
pub fn from_bigint_overflow(value: BigInt) {
interface.from_bigint_overflow(value, iface)
}
pub fn compare(a: Int128, b: Int128) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Int128, b: Int128, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_overflow(a: Int128, b: Int128, op: MathOp) {
interface.math_op_overflow(a, b, iface, op)
pub fn subtract(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn math_op_eject(a: Int128, b: Int128, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn multiply(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn modulo(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn overflow(op: interface.OpResult(Int128)) {
interface.overflow(op, iface)
}
pub fn eject(op: interface.OpResult(Int128)) {
interface.eject(op, iface)
}
fn limits() {

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
const max_limit = 32_767
@ -23,24 +23,44 @@ pub fn to_bigint(uint: Int16) {
uint.data
}
pub fn from_bigint_overflow(value: BigInt) {
interface.from_bigint_overflow(value, iface)
}
pub fn compare(a: Int16, b: Int16) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Int16, b: Int16, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_overflow(a: Int16, b: Int16, op: MathOp) {
interface.math_op_overflow(a, b, iface, op)
pub fn subtract(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn math_op_eject(a: Int16, b: Int16, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn multiply(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn modulo(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn overflow(op: interface.OpResult(Int16)) {
interface.overflow(op, iface)
}
pub fn eject(op: interface.OpResult(Int16)) {
interface.eject(op, iface)
}
fn limits() {

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
const max_limit = 2_147_483_647
@ -23,24 +23,44 @@ pub fn to_bigint(uint: Int32) {
uint.data
}
pub fn from_bigint_overflow(value: BigInt) {
interface.from_bigint_overflow(value, iface)
}
pub fn compare(a: Int32, b: Int32) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Int32, b: Int32, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_overflow(a: Int32, b: Int32, op: MathOp) {
interface.math_op_overflow(a, b, iface, op)
pub fn subtract(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn math_op_eject(a: Int32, b: Int32, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn multiply(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn modulo(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn overflow(op: interface.OpResult(Int32)) {
interface.overflow(op, iface)
}
pub fn eject(op: interface.OpResult(Int32)) {
interface.eject(op, iface)
}
fn limits() {

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
pub opaque type Int64 {
Int64(data: BigInt)
@ -19,24 +19,44 @@ pub fn to_bigint(uint: Int64) {
uint.data
}
pub fn from_bigint_overflow(value: BigInt) {
interface.from_bigint_overflow(value, iface)
}
pub fn compare(a: Int64, b: Int64) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Int64, b: Int64, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_overflow(a: Int64, b: Int64, op: MathOp) {
interface.math_op_overflow(a, b, iface, op)
pub fn subtract(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn math_op_eject(a: Int64, b: Int64, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn multiply(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn modulo(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn overflow(op: interface.OpResult(Int64)) {
interface.overflow(op, iface)
}
pub fn eject(op: interface.OpResult(Int64)) {
interface.eject(op, iface)
}
fn limits() {

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
const max_limit = 127
@ -23,24 +23,44 @@ pub fn to_bigint(uint: Int8) {
uint.data
}
pub fn from_bigint_overflow(value: BigInt) {
interface.from_bigint_overflow(value, iface)
}
pub fn compare(a: Int8, b: Int8) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Int8, b: Int8, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_overflow(a: Int8, b: Int8, op: MathOp) {
interface.math_op_overflow(a, b, iface, op)
pub fn subtract(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn math_op_eject(a: Int8, b: Int8, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn multiply(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn modulo(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn overflow(op: interface.OpResult(Int8)) {
interface.overflow(op, iface)
}
pub fn eject(op: interface.OpResult(Int8)) {
interface.eject(op, iface)
}
fn limits() {

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
const min_limit = 0
@ -25,12 +25,36 @@ pub fn compare(a: Uint, b: Uint) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Uint, b: Uint, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Uint, b: Uint) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_eject(a: Uint, b: Uint, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn subtract(a: Uint, b: Uint) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn multiply(a: Uint, b: Uint) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Uint, b: Uint) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn modulo(a: Uint, b: Uint) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Uint, b: Uint) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Uint, b: Uint) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn eject(op: interface.OpResult(Uint)) {
interface.eject(op, iface)
}
fn limits() {

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
pub opaque type Uint128 {
Uint128(data: BigInt)
@ -19,24 +19,44 @@ pub fn to_bigint(uint: Uint128) {
uint.data
}
pub fn from_bigint_overflow(value: BigInt) {
interface.from_bigint_overflow(value, iface)
}
pub fn compare(a: Uint128, b: Uint128) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Uint128, b: Uint128, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_overflow(a: Uint128, b: Uint128, op: MathOp) {
interface.math_op_overflow(a, b, iface, op)
pub fn subtract(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn math_op_eject(a: Uint128, b: Uint128, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn multiply(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn modulo(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn overflow(op: interface.OpResult(Uint128)) {
interface.overflow(op, iface)
}
pub fn eject(op: interface.OpResult(Uint128)) {
interface.eject(op, iface)
}
fn limits() {

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
const max_limit = 65_535
@ -23,30 +23,50 @@ pub fn to_bigint(uint: Uint16) {
uint.data
}
pub fn from_bigint_overflow(value: BigInt) {
interface.from_bigint_overflow(value, iface)
}
pub fn compare(a: Uint16, b: Uint16) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Uint16, b: Uint16, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_overflow(a: Uint16, b: Uint16, op: MathOp) {
interface.math_op_overflow(a, b, iface, op)
pub fn subtract(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn math_op_eject(a: Uint16, b: Uint16, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn multiply(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn modulo(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn overflow(op: interface.OpResult(Uint16)) {
interface.overflow(op, iface)
}
pub fn eject(op: interface.OpResult(Uint16)) {
interface.eject(op, iface)
}
fn limits() {
interface.overflowable_limits(
bigi.from_int(max_limit),
bigi.from_int(min_limit),
bigi.from_int(max_limit),
)
}

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
pub const max_limit = 4_294_967_295
@ -23,30 +23,50 @@ pub fn to_bigint(uint: Uint32) {
uint.data
}
pub fn from_bigint_overflow(value: BigInt) {
interface.from_bigint_overflow(value, iface)
}
pub fn compare(a: Uint32, b: Uint32) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Uint32, b: Uint32, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_overflow(a: Uint32, b: Uint32, op: MathOp) {
interface.math_op_overflow(a, b, iface, op)
pub fn subtract(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn math_op_eject(a: Uint32, b: Uint32, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn multiply(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn modulo(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn overflow(op: interface.OpResult(Uint32)) {
interface.overflow(op, iface)
}
pub fn eject(op: interface.OpResult(Uint32)) {
interface.eject(op, iface)
}
fn limits() {
interface.overflowable_limits(
bigi.from_int(max_limit),
bigi.from_int(min_limit),
bigi.from_int(max_limit),
)
}

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
pub opaque type Uint64 {
Uint64(data: BigInt)
@ -19,24 +19,44 @@ pub fn to_bigint(uint: Uint64) {
uint.data
}
pub fn from_bigint_overflow(value: BigInt) {
interface.from_bigint_overflow(value, iface)
}
pub fn compare(a: Uint64, b: Uint64) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Uint64, b: Uint64, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_overflow(a: Uint64, b: Uint64, op: MathOp) {
interface.math_op_overflow(a, b, iface, op)
pub fn subtract(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn math_op_eject(a: Uint64, b: Uint64, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn multiply(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn modulo(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn overflow(op: interface.OpResult(Uint64)) {
interface.overflow(op, iface)
}
pub fn eject(op: interface.OpResult(Uint64)) {
interface.eject(op, iface)
}
fn limits() {

View file

@ -1,5 +1,5 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type MathOp, Interface}
import ranged_int/interface.{type Interface, Interface}
const max_limit = 255
@ -23,30 +23,54 @@ pub fn to_bigint(uint: Uint8) {
uint.data
}
pub fn from_bigint_overflow(value: BigInt) {
interface.from_bigint_overflow(value, iface)
}
pub fn compare(a: Uint8, b: Uint8) {
interface.compare(a, b, iface)
}
pub fn math_op(a: Uint8, b: Uint8, op: MathOp) {
interface.math_op(a, b, iface, op)
pub fn add(a: Uint8, b: Uint8) {
interface.math_op(a, b, iface, bigi.add)
}
pub fn math_op_overflow(a: Uint8, b: Uint8, op: MathOp) {
interface.math_op_overflow(a, b, iface, op)
pub fn subtract(a: Uint8, b: Uint8) {
interface.math_op(a, b, iface, bigi.subtract)
}
pub fn math_op_eject(a: Uint8, b: Uint8, op: MathOp) {
interface.math_op_eject(a, b, iface, op)
pub fn multiply(a: Uint8, b: Uint8) {
interface.math_op(a, b, iface, bigi.multiply)
}
pub fn divide(a: Uint8, b: Uint8) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn divide_no_zero(a: Uint8, b: Uint8) {
interface.fallible_op(a, b, iface, bigi.divide_no_zero)
}
pub fn modulo(a: Uint8, b: Uint8) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn remainder(a: Uint8, b: Uint8) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn power(a: Uint8, b: Uint8) {
interface.math_op(a, b, iface, bigi.power)
}
pub fn overflow(op: interface.OpResult(Uint8)) {
interface.overflow(op, iface)
}
pub fn eject(op: interface.OpResult(Uint8)) {
interface.eject(op, iface)
}
fn limits() {
interface.overflowable_limits(
bigi.from_int(max_limit),
bigi.from_int(min_limit),
bigi.from_int(max_limit),
)
}

View file

@ -1,4 +1,5 @@
import gleam/order
import gleam/result
import bigi.{type BigInt}
import ranged_int/limit.{type Limit, NoOverflow, Overflow, Underflow}
import ranged_int/utils
@ -22,8 +23,8 @@ type OverflowableLimits {
OverflowableLimits(min: BigInt, max: BigInt)
}
pub type MathOp =
fn(BigInt, BigInt) -> BigInt
pub type OpResult(a) =
Result(a, utils.Overflow)
pub type Interface(a, overflow_mode) {
Interface(
@ -48,7 +49,7 @@ pub fn min_limit(min: BigInt) -> Limits(NonOverflowable) {
pub fn from_bigint(
value: BigInt,
interface: Interface(a, overflow_mode),
) -> Result(a, utils.Overflow) {
) -> OpResult(a) {
let limits = interface.limits()
case limit.check_limits(value, min: limits.min, max: limits.max) {
NoOverflow -> Ok(interface.from_bigint_unsafe(value))
@ -57,13 +58,6 @@ pub fn from_bigint(
}
}
pub fn from_bigint_overflow(
value: BigInt,
interface: Interface(a, Overflowable),
) -> a {
handle_overflow(value, interface)
}
pub fn compare(
int1: a,
int2: a,
@ -76,8 +70,8 @@ pub fn math_op(
int1: a,
int2: a,
interface: Interface(a, overflow_mode),
op: MathOp,
) -> Result(a, utils.Overflow) {
op: fn(BigInt, BigInt) -> BigInt,
) -> OpResult(a) {
let limits = interface.limits()
let bigint1 = interface.to_bigint(int1)
let bigint2 = interface.to_bigint(int2)
@ -89,48 +83,51 @@ pub fn math_op(
}
}
pub fn math_op_overflow(
int1: a,
int2: a,
interface: Interface(a, Overflowable),
op: MathOp,
) -> a {
let bigint1 = interface.to_bigint(int1)
let bigint2 = interface.to_bigint(int2)
let result = op(bigint1, bigint2)
handle_overflow(result, interface)
}
pub fn math_op_eject(
pub fn fallible_op(
int1: a,
int2: a,
interface: Interface(a, overflow_mode),
op: MathOp,
) -> BigInt {
op: fn(BigInt, BigInt) -> Result(BigInt, op_err),
) -> Result(OpResult(a), op_err) {
let limits = interface.limits()
let bigint1 = interface.to_bigint(int1)
let bigint2 = interface.to_bigint(int2)
op(bigint1, bigint2)
use result <- result.try(op(bigint1, bigint2))
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))
})
}
pub fn handle_overflow(value: BigInt, interface: Interface(a, Overflowable)) {
let limits = interface.limits()
let result = case
limit.check_limits(value, min: limits.min, max: limits.max)
{
NoOverflow -> value
Overflow(amount) -> {
let OverflowableLimits(min, max) = destructure_limits(limits)
utils.overflow(utils.DidOverflow(amount), min: min, max: max)
}
Underflow(amount) -> {
let OverflowableLimits(min, max) = destructure_limits(limits)
utils.overflow(utils.DidUnderflow(amount), min: min, max: max)
pub fn overflow(value: OpResult(a), interface: Interface(a, Overflowable)) {
case value {
Ok(new_value) -> new_value
Error(overflow) -> {
let OverflowableLimits(min, max) = destructure_limits(interface.limits())
utils.overflow(overflow, min: min, max: max)
|> interface.from_bigint_unsafe()
}
}
}
pub fn eject(value: OpResult(a), interface: Interface(a, overflow_mode)) {
case value {
Ok(new_value) -> interface.to_bigint(new_value)
Error(overflow) -> {
case overflow, interface.limits() {
utils.DidOverflow(amount), Limits(max: limit.Bounded(max), ..) ->
bigi.add(max, amount)
utils.DidUnderflow(amount), Limits(min: limit.Bounded(min), ..) ->
bigi.subtract(min, amount)
_, _ -> panic as "Overflowed but there was no corresponding limit (o_O)"
}
}
}
interface.from_bigint_unsafe(result)
}
fn destructure_limits(limits: Limits(Overflowable)) {
// We can trust that overflowable limits are always bounded on both sides
let assert limit.Bounded(min) = limits.min
let assert limit.Bounded(max) = limits.max
OverflowableLimits(min: min, max: max)

View file

@ -0,0 +1,10 @@
import bigi
import gleeunit/should
import ranged_int/builtin/uint16
pub fn add_test() {
let assert Ok(a) = uint16.from_bigint(bigi.zero())
let assert Ok(b) = uint16.from_bigint(bigi.from_int(12))
let c = uint16.eject(uint16.add(a, b))
should.equal(c, bigi.from_int(12))
}

View file

@ -3,8 +3,15 @@ import gleeunit/should
import ranged_int/builtin/uint8
pub fn add_test() {
let a = uint8.from_bigint_overflow(bigi.zero())
let b = uint8.from_bigint_overflow(bigi.from_int(12))
let c = uint8.math_op_overflow(a, b, bigi.add)
should.equal(c, uint8.from_bigint_overflow(bigi.from_int(12)))
let assert Ok(a) = uint8.from_bigint(bigi.zero())
let assert Ok(b) = uint8.from_bigint(bigi.from_int(12))
let c = uint8.eject(uint8.add(a, b))
should.equal(c, bigi.from_int(12))
}
pub fn divide_test() {
let assert Ok(a) = uint8.from_bigint(bigi.from_int(120))
let assert Ok(b) = uint8.from_bigint(bigi.from_int(12))
let assert Ok(c) = uint8.divide_no_zero(a, b)
should.equal(uint8.eject(c), bigi.from_int(10))
}