Added fallible ops and generic ranged int
This commit is contained in:
parent
c0e4dbc4ed
commit
b02def4f40
13 changed files with 241 additions and 4 deletions
|
@ -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,
|
||||
)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
|
11
test/builtin/generic_test.gleam
Normal file
11
test/builtin/generic_test.gleam
Normal 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))
|
||||
}
|
Loading…
Reference in a new issue