-module(bigi_ffi). -export([ from/1, from_string/1, to/1, zero/0, compare/2, add/2, subtract/2, multiply/2, divide/2, divide_no_zero/2, remainder/2, remainder_no_zero/2, modulo/2, modulo_no_zero/2, power/2, decode/1 ]). from(Int) -> Int. from_string(Str) -> case string:to_integer(Str) of {_, Rest} when Rest /= <<"">> -> {error, nil}; {Int, _} -> {ok, Int} end. to(BigInt) -> {ok, BigInt}. zero() -> 0. compare(A, B) when A < B -> lt; compare(A, B) when A > B -> gt; compare(_, _) -> eq. add(A, B) -> A + B. subtract(A, B) -> A - B. multiply(A, B) -> A * B. divide(_, 0) -> 0; divide(A, B) -> A div B. divide_no_zero(_, 0) -> {error, nil}; divide_no_zero(A, B) -> {ok, divide(A, B)}. remainder(_, 0) -> 0; remainder(A, B) -> A rem B. remainder_no_zero(_, 0) -> {error, nil}; remainder_no_zero(A, B) -> {ok, remainder(A, B)}. modulo(_, 0) -> 0; modulo(A, B) -> ((A rem B) + B) rem B. modulo_no_zero(_, 0) -> {error, nil}; modulo_no_zero(A, B) -> {ok, modulo(A, B)}. power(_, Exp) when Exp < 0 -> {error, nil}; power(Base, Exp) -> {ok, do_power(Base, Exp)}. do_power(_, 0) -> 1; do_power(A, 1) -> A; do_power(A, N) -> B = do_power(A, N div 2), B * B * (case N rem 2 of 0 -> 1; 1 -> A end). decode(Dyn) when is_integer(Dyn) -> {ok, Dyn}; decode(Dyn) -> {error, {decode_error, <<"bigint">>, get_type(Dyn), []}}. get_type(Val) when is_atom(Val) -> <<"atom">>; get_type(Val) when is_function(Val) -> <<"function">>; get_type(Val) when is_pid(Val) -> <<"pid">>; get_type(Val) when is_binary(Val) -> <<"binary">>; get_type(Val) when is_list(Val) -> <<"list">>; get_type(Val) when is_map(Val) -> <<"map">>; get_type(Val) when is_reference(Val) -> <<"reference">>; get_type(Val) when is_float(Val) -> <<"float">>; get_type(Val) when is_tuple(Val) -> <<"tuple">>; get_type(Val) when is_port(Val) -> <<"port">>; get_type(Val) when is_bitstring(Val) -> <<"bitstring">>.