VSSL/source/library/vssl-integers-generic_digit...

61 lines
2.1 KiB
Ada

--
-- Base for building big numbers
-- Arrays representing series of digits. Digits beyond array bounds are supposed to be 0
--
pragma SPARK_Mode;
generic
type Digit_Type is mod <>;
type Index is range <>;
type Digit_Array is array (Index range <>) of Digit_Type;
package VSSL.Integers.Generic_Digit_Arrays is
function Element (X : Digit_Array; I : Index) return Digit_Type
is (if I in X'Range then X (I) else 0);
-- Generalized index
function First_Nonzero (X : Digit_Array) return Index'Base;
-- Returns index of first (least significant) nonzero element or Index'Base'Last if all zero
function Last_Nonzero (X : Digit_Array) return Index'Base;
-- Returns index of last (most significant) nonzero element or Index'Base'First if all zero
function Is_Zero (X : Digit_Array) return Boolean
is (for all I in X'Range => X (I) = 0);
-- Is a digit array represents 0
function Is_Fit (X : Digit_Array; First, Last : Index'Base) return Boolean
is ((First <= X'First or else Is_Zero (X (X'First .. Index'Min (Index'Pred (First), X'Last))))
and then
(Last >= X'Last or else Is_Zero (X (Index'Max (Index'Succ (Last), X'First) .. X'Last))));
-- Can array X be copied to an array with bounds (First .. Last) without loss
function Is_Fit (X, Y : Digit_Array) return Boolean
is (Is_Fit (X, Y'First, Y'Last));
-- Can array X be copied to Y without loss
function Left_Equal (X, Y : Digit_Array) return Boolean
is (for all J in X'Range => X (J) = Element (Y, J));
function "=" (X, Y : Digit_Array) return Boolean
with Post => "="'Result = (Left_Equal (X, Y) and Left_Equal (Y, X));
-- Are two digit arrays represent one number
function "<" (X, Y : Digit_Array) return Boolean;
-- Is most significant differing digit in X is less than one in Y
function ">" (X, Y : Digit_Array) return Boolean is (Y < X);
function "<=" (X, Y : Digit_Array) return Boolean is (not (X > Y));
function ">=" (X, Y : Digit_Array) return Boolean is (not (X < Y));
procedure Set (
X : out Digit_Array;
Y : in Digit_Array)
with
Pre => Is_Fit (Y, X'First, X'Last),
Post => Left_Equal (X, Y) and Left_Equal (Y, X);
end VSSL.Integers.Generic_Digit_Arrays;