Packages

Type safe ranged integer operations for Gleam.

Current section

Files

Jump to
ranged_int src ranged_int@builtin@generic.erl
Raw

src/ranged_int@builtin@generic.erl

-module(ranged_int@builtin@generic).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([to_bigint/1, get_interface/1, compare/2, absolute/1, add/2, subtract/2, multiply/2, divide/2, divide_no_zero/2, modulo/2, modulo_no_zero/2, remainder/2, remainder_no_zero/2, power/2, overflow/2, eject/2, from_bigint_overflowable/3, from_bigint_min/2, from_bigint_max/2]).
-export_type([generic_interface/1, ranged_int/1]).
-opaque generic_interface(FXU) :: {generic_interface,
ranged_int@interface:interface(ranged_int(FXU), FXU)}.
-opaque ranged_int(FXV) :: {ranged_int,
bigi:big_int(),
fun(() -> ranged_int@interface:interface(ranged_int(FXV), FXV))}.
-spec to_bigint(ranged_int(any())) -> bigi:big_int().
to_bigint(Int) ->
erlang:element(2, Int).
-spec get_interface(ranged_int(FYC)) -> generic_interface(FYC).
get_interface(Int) ->
{generic_interface, (erlang:element(3, Int))()}.
-spec compare(ranged_int(FYF), ranged_int(FYF)) -> gleam@order:order().
compare(A, B) ->
ranged_int@interface:compare(A, B, (erlang:element(3, A))()).
-spec absolute(ranged_int(FYJ)) -> {ok, ranged_int(FYJ)} |
{error, ranged_int@utils:overflow()}.
absolute(A) ->
ranged_int@interface:math_op_unary(
A,
(erlang:element(3, A))(),
fun erlang:abs/1
).
-spec add(ranged_int(FYM), bigi:big_int()) -> {ok, ranged_int(FYM)} |
{error, ranged_int@utils:overflow()}.
add(A, B) ->
ranged_int@interface:math_op(
A,
B,
(erlang:element(3, A))(),
fun bigi_ffi:add/2
).
-spec subtract(ranged_int(FYP), bigi:big_int()) -> {ok, ranged_int(FYP)} |
{error, ranged_int@utils:overflow()}.
subtract(A, B) ->
ranged_int@interface:math_op(
A,
B,
(erlang:element(3, A))(),
fun bigi_ffi:subtract/2
).
-spec multiply(ranged_int(FYS), bigi:big_int()) -> {ok, ranged_int(FYS)} |
{error, ranged_int@utils:overflow()}.
multiply(A, B) ->
ranged_int@interface:math_op(
A,
B,
(erlang:element(3, A))(),
fun bigi_ffi:multiply/2
).
-spec divide(ranged_int(FYV), bigi:big_int()) -> {ok, ranged_int(FYV)} |
{error, ranged_int@utils:overflow()}.
divide(A, B) ->
ranged_int@interface:math_op(
A,
B,
(erlang:element(3, A))(),
fun bigi_ffi:divide/2
).
-spec divide_no_zero(ranged_int(FYY), bigi:big_int()) -> {ok,
{ok, ranged_int(FYY)} | {error, ranged_int@utils:overflow()}} |
{error, nil}.
divide_no_zero(A, B) ->
ranged_int@interface:fallible_op(
A,
B,
(erlang:element(3, A))(),
fun bigi_ffi:divide_no_zero/2
).
-spec modulo(ranged_int(FZB), bigi:big_int()) -> {ok, ranged_int(FZB)} |
{error, ranged_int@utils:overflow()}.
modulo(A, B) ->
ranged_int@interface:math_op(
A,
B,
(erlang:element(3, A))(),
fun bigi_ffi:modulo/2
).
-spec modulo_no_zero(ranged_int(FZE), bigi:big_int()) -> {ok,
{ok, ranged_int(FZE)} | {error, ranged_int@utils:overflow()}} |
{error, nil}.
modulo_no_zero(A, B) ->
ranged_int@interface:fallible_op(
A,
B,
(erlang:element(3, A))(),
fun bigi_ffi:modulo_no_zero/2
).
-spec remainder(ranged_int(FZH), bigi:big_int()) -> {ok, ranged_int(FZH)} |
{error, ranged_int@utils:overflow()}.
remainder(A, B) ->
ranged_int@interface:math_op(
A,
B,
(erlang:element(3, A))(),
fun bigi_ffi:remainder/2
).
-spec remainder_no_zero(ranged_int(FZK), bigi:big_int()) -> {ok,
{ok, ranged_int(FZK)} | {error, ranged_int@utils:overflow()}} |
{error, nil}.
remainder_no_zero(A, B) ->
ranged_int@interface:fallible_op(
A,
B,
(erlang:element(3, A))(),
fun bigi_ffi:remainder_no_zero/2
).
-spec power(ranged_int(FZN), ranged_int@builtin@uint:uint()) -> {ok,
ranged_int(FZN)} |
{error, ranged_int@utils:overflow()}.
power(A, B) ->
_assert_subject = ranged_int@interface:fallible_op(
A,
ranged_int@builtin@uint:to_bigint(B),
(erlang:element(3, A))(),
fun bigi_ffi:power/2
),
{ok, Result} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"ranged_int/builtin/generic"/utf8>>,
function => <<"power"/utf8>>,
line => 101})
end,
Result.
-spec overflow(
{ok, ranged_int(ranged_int@interface:overflowable())} |
{error, ranged_int@utils:overflow()},
generic_interface(ranged_int@interface:overflowable())
) -> ranged_int(ranged_int@interface:overflowable()).
overflow(Op, Interface) ->
ranged_int@interface:overflow(Op, erlang:element(2, Interface)).
-spec eject(
{ok, ranged_int(FZU)} | {error, ranged_int@utils:overflow()},
generic_interface(FZU)
) -> bigi:big_int().
eject(Op, Interface) ->
ranged_int@interface:eject(Op, erlang:element(2, Interface)).
-spec gen_overflowable_interface(bigi:big_int(), bigi:big_int()) -> ranged_int@interface:interface(ranged_int(ranged_int@interface:overflowable()), ranged_int@interface:overflowable()).
gen_overflowable_interface(Min, Max) ->
{interface,
fun to_bigint/1,
fun(B) ->
{ranged_int, B, fun() -> gen_overflowable_interface(Min, Max) end}
end,
fun() -> ranged_int@interface:overflowable_limits(Min, Max) end}.
-spec from_bigint_overflowable(bigi:big_int(), bigi:big_int(), bigi:big_int()) -> {ok,
ranged_int(ranged_int@interface:overflowable())} |
{error, ranged_int@utils:overflow()}.
from_bigint_overflowable(Value, Min, Max) ->
Iface = gen_overflowable_interface(Min, Max),
ranged_int@interface:from_bigint(Value, Iface).
-spec gen_min_interface(bigi:big_int()) -> ranged_int@interface:interface(ranged_int(ranged_int@interface:non_overflowable()), ranged_int@interface:non_overflowable()).
gen_min_interface(Min) ->
{interface,
fun to_bigint/1,
fun(B) -> {ranged_int, B, fun() -> gen_min_interface(Min) end} end,
fun() -> ranged_int@interface:min_limit(Min) end}.
-spec from_bigint_min(bigi:big_int(), bigi:big_int()) -> {ok,
ranged_int(ranged_int@interface:non_overflowable())} |
{error, ranged_int@utils:overflow()}.
from_bigint_min(Value, Min) ->
Iface = gen_min_interface(Min),
ranged_int@interface:from_bigint(Value, Iface).
-spec gen_max_interface(bigi:big_int()) -> ranged_int@interface:interface(ranged_int(ranged_int@interface:non_overflowable()), ranged_int@interface:non_overflowable()).
gen_max_interface(Max) ->
{interface,
fun to_bigint/1,
fun(B) -> {ranged_int, B, fun() -> gen_max_interface(Max) end} end,
fun() -> ranged_int@interface:max_limit(Max) end}.
-spec from_bigint_max(bigi:big_int(), bigi:big_int()) -> {ok,
ranged_int(ranged_int@interface:non_overflowable())} |
{error, ranged_int@utils:overflow()}.
from_bigint_max(Value, Max) ->
Iface = gen_max_interface(Max),
ranged_int@interface:from_bigint(Value, Iface).