Added fallible ops and generic ranged int

This commit is contained in:
Mikko Ahlroth 2024-02-11 00:05:26 +02:00
parent c0e4dbc4ed
commit b02def4f40
13 changed files with 241 additions and 4 deletions

View file

@ -0,0 +1,113 @@
import bigi.{type BigInt}
import ranged_int/interface.{type Interface, type Overflowable, Interface}
pub type GenericInterface(overflow_mode) =
Interface(RangedInt(overflow_mode), overflow_mode)
pub opaque type RangedInt(overflow_mode) {
RangedInt(
data: BigInt,
interface: fn() -> Interface(RangedInt(overflow_mode), overflow_mode),
)
}
pub fn from_bigint_overflowable(value: BigInt, min min: BigInt, max max: BigInt) {
let iface = gen_overflowable_interface(min, max)
interface.from_bigint(value, iface)
}
pub fn from_bigint_min(value: BigInt, min min: BigInt) {
let iface = gen_min_interface(min)
interface.from_bigint(value, iface)
}
pub fn from_bigint_max(value: BigInt, max max: BigInt) {
let iface = gen_max_interface(max)
interface.from_bigint(value, iface)
}
pub fn to_bigint(uint: RangedInt(overflow_mode)) {
uint.data
}
pub fn compare(a: RangedInt(overflow_mode), b: RangedInt(overflow_mode)) {
interface.compare(a, b, a.interface())
}
pub fn add(a: RangedInt(overflow_mode), b: RangedInt(overflow_mode)) {
interface.math_op(a, b, a.interface(), bigi.add)
}
pub fn subtract(a: RangedInt(overflow_mode), b: RangedInt(overflow_mode)) {
interface.math_op(a, b, a.interface(), bigi.subtract)
}
pub fn multiply(a: RangedInt(overflow_mode), b: RangedInt(overflow_mode)) {
interface.math_op(a, b, a.interface(), bigi.multiply)
}
pub fn divide(a: RangedInt(overflow_mode), b: RangedInt(overflow_mode)) {
interface.math_op(a, b, a.interface(), bigi.divide)
}
pub fn modulo(a: RangedInt(overflow_mode), b: RangedInt(overflow_mode)) {
interface.math_op(a, b, a.interface(), bigi.modulo)
}
pub fn remainder(a: RangedInt(overflow_mode), b: RangedInt(overflow_mode)) {
interface.math_op(a, b, a.interface(), bigi.remainder)
}
pub fn power(a: RangedInt(overflow_mode), b: RangedInt(overflow_mode)) {
interface.math_op(a, b, a.interface(), bigi.power)
}
pub fn overflow2(
a: RangedInt(Overflowable),
b: RangedInt(Overflowable),
op: fn(RangedInt(Overflowable), RangedInt(Overflowable)) ->
interface.OpResult(RangedInt(Overflowable)),
) {
interface.overflow(op(a, b), a.interface())
}
pub fn eject2(
a: RangedInt(overflow_mode),
b: RangedInt(overflow_mode),
op: fn(RangedInt(overflow_mode), RangedInt(overflow_mode)) ->
interface.OpResult(RangedInt(overflow_mode)),
) {
interface.eject(op(a, b), a.interface())
}
fn gen_overflowable_interface(min: BigInt, max: BigInt) {
Interface(
from_bigint_unsafe: fn(b: BigInt) {
RangedInt(data: b, interface: fn() {
gen_overflowable_interface(min, max)
})
},
limits: fn() { interface.overflowable_limits(min, max) },
to_bigint: to_bigint,
)
}
fn gen_min_interface(min: BigInt) {
Interface(
from_bigint_unsafe: fn(b: BigInt) {
RangedInt(data: b, interface: fn() { gen_min_interface(min) })
},
limits: fn() { interface.min_limit(min) },
to_bigint: to_bigint,
)
}
fn gen_max_interface(max: BigInt) {
Interface(
from_bigint_unsafe: fn(b: BigInt) {
RangedInt(data: b, interface: fn() { gen_max_interface(max) })
},
limits: fn() { interface.max_limit(max) },
to_bigint: to_bigint,
)
}

View file

@ -39,14 +39,26 @@ pub fn divide(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn divide_no_zero(a: Int128, b: Int128) {
interface.fallible_op(a, b, iface, bigi.divide_no_zero)
}
pub fn modulo(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn modulo_no_zero(a: Int128, b: Int128) {
interface.fallible_op(a, b, iface, bigi.modulo_no_zero)
}
pub fn remainder(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn remainder_no_zero(a: Int128, b: Int128) {
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
}
pub fn power(a: Int128, b: Int128) {
interface.math_op(a, b, iface, bigi.power)
}

View file

@ -43,14 +43,26 @@ pub fn divide(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn divide_no_zero(a: Int16, b: Int16) {
interface.fallible_op(a, b, iface, bigi.divide_no_zero)
}
pub fn modulo(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn modulo_no_zero(a: Int16, b: Int16) {
interface.fallible_op(a, b, iface, bigi.modulo_no_zero)
}
pub fn remainder(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn remainder_no_zero(a: Int16, b: Int16) {
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
}
pub fn power(a: Int16, b: Int16) {
interface.math_op(a, b, iface, bigi.power)
}

View file

@ -43,14 +43,26 @@ pub fn divide(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn divide_no_zero(a: Int32, b: Int32) {
interface.fallible_op(a, b, iface, bigi.divide_no_zero)
}
pub fn modulo(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn modulo_no_zero(a: Int32, b: Int32) {
interface.fallible_op(a, b, iface, bigi.modulo_no_zero)
}
pub fn remainder(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn remainder_no_zero(a: Int32, b: Int32) {
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
}
pub fn power(a: Int32, b: Int32) {
interface.math_op(a, b, iface, bigi.power)
}

View file

@ -39,14 +39,26 @@ pub fn divide(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn divide_no_zero(a: Int64, b: Int64) {
interface.fallible_op(a, b, iface, bigi.divide_no_zero)
}
pub fn modulo(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn modulo_no_zero(a: Int64, b: Int64) {
interface.fallible_op(a, b, iface, bigi.modulo_no_zero)
}
pub fn remainder(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn remainder_no_zero(a: Int64, b: Int64) {
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
}
pub fn power(a: Int64, b: Int64) {
interface.math_op(a, b, iface, bigi.power)
}

View file

@ -43,14 +43,26 @@ pub fn divide(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn divide_no_zero(a: Int8, b: Int8) {
interface.fallible_op(a, b, iface, bigi.divide_no_zero)
}
pub fn modulo(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn modulo_no_zero(a: Int8, b: Int8) {
interface.fallible_op(a, b, iface, bigi.modulo_no_zero)
}
pub fn remainder(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn remainder_no_zero(a: Int8, b: Int8) {
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
}
pub fn power(a: Int8, b: Int8) {
interface.math_op(a, b, iface, bigi.power)
}

View file

@ -39,14 +39,26 @@ pub fn divide(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn divide_no_zero(a: Uint128, b: Uint128) {
interface.fallible_op(a, b, iface, bigi.divide_no_zero)
}
pub fn modulo(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn modulo_no_zero(a: Uint128, b: Uint128) {
interface.fallible_op(a, b, iface, bigi.modulo_no_zero)
}
pub fn remainder(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn remainder_no_zero(a: Uint128, b: Uint128) {
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
}
pub fn power(a: Uint128, b: Uint128) {
interface.math_op(a, b, iface, bigi.power)
}

View file

@ -43,14 +43,26 @@ pub fn divide(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn divide_no_zero(a: Uint16, b: Uint16) {
interface.fallible_op(a, b, iface, bigi.divide_no_zero)
}
pub fn modulo(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn modulo_no_zero(a: Uint16, b: Uint16) {
interface.fallible_op(a, b, iface, bigi.modulo_no_zero)
}
pub fn remainder(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn remainder_no_zero(a: Uint16, b: Uint16) {
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
}
pub fn power(a: Uint16, b: Uint16) {
interface.math_op(a, b, iface, bigi.power)
}

View file

@ -43,14 +43,26 @@ pub fn divide(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn divide_no_zero(a: Uint32, b: Uint32) {
interface.fallible_op(a, b, iface, bigi.divide_no_zero)
}
pub fn modulo(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn modulo_no_zero(a: Uint32, b: Uint32) {
interface.fallible_op(a, b, iface, bigi.modulo_no_zero)
}
pub fn remainder(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn remainder_no_zero(a: Uint32, b: Uint32) {
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
}
pub fn power(a: Uint32, b: Uint32) {
interface.math_op(a, b, iface, bigi.power)
}

View file

@ -39,14 +39,26 @@ pub fn divide(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.divide)
}
pub fn divide_no_zero(a: Uint64, b: Uint64) {
interface.fallible_op(a, b, iface, bigi.divide_no_zero)
}
pub fn modulo(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn modulo_no_zero(a: Uint64, b: Uint64) {
interface.fallible_op(a, b, iface, bigi.modulo_no_zero)
}
pub fn remainder(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn remainder_no_zero(a: Uint64, b: Uint64) {
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
}
pub fn power(a: Uint64, b: Uint64) {
interface.math_op(a, b, iface, bigi.power)
}

View file

@ -51,10 +51,18 @@ pub fn modulo(a: Uint8, b: Uint8) {
interface.math_op(a, b, iface, bigi.modulo)
}
pub fn modulo_no_zero(a: Uint8, b: Uint8) {
interface.fallible_op(a, b, iface, bigi.modulo_no_zero)
}
pub fn remainder(a: Uint8, b: Uint8) {
interface.math_op(a, b, iface, bigi.remainder)
}
pub fn remainder_no_zero(a: Uint8, b: Uint8) {
interface.fallible_op(a, b, iface, bigi.remainder_no_zero)
}
pub fn power(a: Uint8, b: Uint8) {
interface.math_op(a, b, iface, bigi.power)
}

View file

@ -4,9 +4,6 @@ import bigi.{type BigInt}
import ranged_int/limit.{type Limit, NoOverflow, Overflow, Underflow}
import ranged_int/utils
type Constructor(a) =
fn(BigInt) -> a
pub type Overflowable {
Overflowable
}
@ -29,7 +26,7 @@ pub type OpResult(a) =
pub type Interface(a, overflow_mode) {
Interface(
to_bigint: fn(a) -> BigInt,
from_bigint_unsafe: Constructor(a),
from_bigint_unsafe: fn(BigInt) -> a,
limits: fn() -> Limits(overflow_mode),
)
}

View file

@ -0,0 +1,11 @@
import bigi
import gleeunit/should
import ranged_int/builtin/generic
pub fn add_test() {
let assert Ok(a) = generic.from_bigint_min(bigi.zero(), min: bigi.zero())
let assert Ok(b) =
generic.from_bigint_max(bigi.from_int(12), max: bigi.from_int(12))
let c = generic.eject2(a, b, fn(a, b) { generic.add(a, b) })
should.equal(c, bigi.from_int(12))
}