-module(ranged_int@internal@limit). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([check_limits/3]). -export_type([limit/0, limit_check/0]). -type limit() :: {bounded, bigi:big_int()} | unbounded. -type limit_check() :: no_overflow | {overflow, bigi:big_int()} | {underflow, bigi:big_int()}. -spec diff(limit(), bigi:big_int()) -> bigi:big_int(). diff(Limit, Value) -> case Limit of unbounded -> bigi_ffi:zero(); {bounded, Lim} -> bigi_ffi:subtract(Value, Lim) end. -spec check_limits(bigi:big_int(), limit(), limit()) -> limit_check(). check_limits(Value, Min, Max) -> Max_diff = diff(Max, Value), case bigi_ffi:compare(Max_diff, bigi_ffi:zero()) of gt -> {overflow, Max_diff}; eq -> Min_diff = diff(Min, Value), case bigi_ffi:compare(Min_diff, bigi_ffi:zero()) of lt -> {underflow, bigi_ffi:multiply(Min_diff, bigi_ffi:from(-1))}; eq -> no_overflow; gt -> no_overflow end; lt -> Min_diff = diff(Min, Value), case bigi_ffi:compare(Min_diff, bigi_ffi:zero()) of lt -> {underflow, bigi_ffi:multiply(Min_diff, bigi_ffi:from(-1))}; eq -> no_overflow; gt -> no_overflow end end.