1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- S Y S T E M . B I G N U M S --
9 -- Copyright (C) 2012-2018, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- This package provides arbitrary precision signed integer arithmetic for
33 -- use in computing intermediate values in expressions for the case where
34 -- pragma Overflow_Check (Eliminate) is in effect.
36 with System
; use System
;
37 with System
.Secondary_Stack
; use System
.Secondary_Stack
;
38 with System
.Storage_Elements
; use System
.Storage_Elements
;
40 package body System
.Bignums
is
43 -- So that operations on Unsigned_32 are available
45 type DD
is mod Base
** 2;
46 -- Double length digit used for intermediate computations
48 function MSD
(X
: DD
) return SD
is (SD
(X
/ Base
));
49 function LSD
(X
: DD
) return SD
is (SD
(X
mod Base
));
50 -- Most significant and least significant digit of double digit value
52 function "&" (X
, Y
: SD
) return DD
is (DD
(X
) * Base
+ DD
(Y
));
53 -- Compose double digit value from two single digit values
55 subtype LLI
is Long_Long_Integer;
57 One_Data
: constant Digit_Vector
(1 .. 1) := (1 => 1);
60 Zero_Data
: constant Digit_Vector
(1 .. 0) := (1 .. 0 => 0);
63 -----------------------
64 -- Local Subprograms --
65 -----------------------
70 Y_Neg
: Boolean) return Bignum
72 Pre
=> X
'First = 1 and then Y
'First = 1;
73 -- This procedure adds two signed numbers returning the Sum, it is used
74 -- for both addition and subtraction. The value computed is X + Y, with
75 -- X_Neg and Y_Neg giving the signs of the operands.
77 function Allocate_Bignum
(Len
: Length
) return Bignum
with
78 Post
=> Allocate_Bignum
'Result.Len
= Len
;
79 -- Allocate Bignum value of indicated length on secondary stack. On return
80 -- the Neg and D fields are left uninitialized.
82 type Compare_Result
is (LT
, EQ
, GT
);
83 -- Indicates result of comparison in following call
87 X_Neg
, Y_Neg
: Boolean) return Compare_Result
89 Pre
=> X
'First = 1 and then Y
'First = 1;
90 -- Compare (X with sign X_Neg) with (Y with sign Y_Neg), and return the
91 -- result of the signed comparison.
95 Quotient
: out Bignum
;
96 Remainder
: out Bignum
;
97 Discard_Quotient
: Boolean := False;
98 Discard_Remainder
: Boolean := False);
99 -- Returns the Quotient and Remainder from dividing abs (X) by abs (Y). The
100 -- values of X and Y are not modified. If Discard_Quotient is True, then
101 -- Quotient is undefined on return, and if Discard_Remainder is True, then
102 -- Remainder is undefined on return. Service routine for Big_Div/Rem/Mod.
104 procedure Free_Bignum
(X
: Bignum
) is null;
105 -- Called to free a Bignum value used in intermediate computations. In
106 -- this implementation using the secondary stack, it does nothing at all,
107 -- because we rely on Mark/Release, but it may be of use for some
108 -- alternative implementation.
112 Neg
: Boolean := False) return Bignum
;
113 -- Given a digit vector and sign, allocate and construct a Bignum value.
114 -- Note that X may have leading zeroes which must be removed, and if the
115 -- result is zero, the sign is forced positive.
122 (X
, Y
: Digit_Vector
;
124 Y_Neg
: Boolean) return Bignum
127 -- If signs are the same, we are doing an addition, it is convenient to
128 -- ensure that the first operand is the longer of the two.
130 if X_Neg
= Y_Neg
then
131 if X
'Last < Y
'Last then
132 return Add
(X
=> Y
, Y
=> X
, X_Neg
=> Y_Neg
, Y_Neg
=> X_Neg
);
134 -- Here signs are the same, and the first operand is the longer
137 pragma Assert
(X_Neg
= Y_Neg
and then X
'Last >= Y
'Last);
139 -- Do addition, putting result in Sum (allowing for carry)
142 Sum
: Digit_Vector
(0 .. X
'Last);
147 for J
in reverse 1 .. X
'Last loop
148 RD
:= RD
+ DD
(X
(J
));
150 if J
>= 1 + (X
'Last - Y
'Last) then
151 RD
:= RD
+ DD
(Y
(J
- (X
'Last - Y
'Last)));
159 return Normalize
(Sum
, X_Neg
);
163 -- Signs are different so really this is a subtraction, we want to make
164 -- sure that the largest magnitude operand is the first one, and then
165 -- the result will have the sign of the first operand.
169 CR
: constant Compare_Result
:= Compare
(X
, Y
, False, False);
173 return Normalize
(Zero_Data
);
176 return Add
(X
=> Y
, Y
=> X
, X_Neg
=> Y_Neg
, Y_Neg
=> X_Neg
);
179 pragma Assert
(X_Neg
/= Y_Neg
and then CR
= GT
);
181 -- Do subtraction, putting result in Diff
184 Diff
: Digit_Vector
(1 .. X
'Length);
189 for J
in reverse 1 .. X
'Last loop
190 RD
:= RD
+ DD
(X
(J
));
192 if J
>= 1 + (X
'Last - Y
'Last) then
193 RD
:= RD
- DD
(Y
(J
- (X
'Last - Y
'Last)));
196 Diff
(J
) := LSD
(RD
);
197 RD
:= (if RD
< Base
then 0 else -1);
200 return Normalize
(Diff
, X_Neg
);
207 ---------------------
208 -- Allocate_Bignum --
209 ---------------------
211 function Allocate_Bignum
(Len
: Length
) return Bignum
is
215 -- Change the if False here to if True to get allocation on the heap
216 -- instead of the secondary stack, which is convenient for debugging
217 -- System.Bignum itself.
223 B
:= new Bignum_Data
'(Len, False, (others => 0));
227 -- Normal case of allocation on the secondary stack
230 -- Note: The approach used here is designed to avoid strict aliasing
231 -- warnings that appeared previously using unchecked conversion.
233 SS_Allocate (Addr, Storage_Offset (4 + 4 * Len));
237 for B'Address use Addr'Address;
238 pragma Import (Ada, B);
240 BD : Bignum_Data (Len);
241 for BD'Address use Addr;
242 pragma Import (Ada, BD);
244 -- Expose a writable view of discriminant BD.Len so that we can
245 -- initialize it. We need to use the exact layout of the record
246 -- to ensure that the Length field has 24 bits as expected.
248 type Bignum_Data_Header is record
253 for Bignum_Data_Header use record
254 Len at 0 range 0 .. 23;
255 Neg at 3 range 0 .. 7;
258 BDH : Bignum_Data_Header;
259 for BDH'Address use BD'Address;
260 pragma Import (Ada, BDH);
262 pragma Assert (BDH.Len'Size = BD.Len'Size);
275 function Big_Abs (X : Bignum) return Bignum is
277 return Normalize (X.D);
284 function Big_Add (X, Y : Bignum) return Bignum is
286 return Add (X.D, Y.D, X.Neg, Y.Neg);
293 -- This table is excerpted from RM 4.5.5(28-30) and shows how the result
294 -- varies with the signs of the operands.
312 function Big_Div (X, Y : Bignum) return Bignum is
315 Div_Rem (X, Y, Q, R, Discard_Remainder => True);
316 Q.Neg := Q.Len > 0 and then (X.Neg xor Y.Neg);
324 function Big_Exp (X, Y : Bignum) return Bignum is
326 function "**" (X : Bignum; Y : SD) return Bignum;
327 -- Internal routine where we know right operand is one word
333 function "**" (X : Bignum; Y : SD) return Bignum is
340 return Normalize (One_Data);
345 return Normalize (X.D);
350 return Big_Mul (X, X);
352 -- For X greater than 2, use the recursion
354 -- X even, X ** Y = (X ** (Y/2)) ** 2;
355 -- X odd, X ** Y = (X ** (Y/2)) ** 2 * X;
359 XY2 : constant Bignum := X ** (Y / 2);
360 XY2S : constant Bignum := Big_Mul (XY2, XY2);
366 -- Raise storage error if intermediate value is getting too
367 -- large, which we arbitrarily define as 200 words for now.
369 if XY2S.Len > 200 then
371 raise Storage_Error with
372 "exponentiation result is too large";
375 -- Otherwise take care of even/odd cases
377 if (Y and 1) = 0 then
381 Res := Big_Mul (XY2S, X);
389 -- Start of processing for Big_Exp
392 -- Error if right operand negative
395 raise Constraint_Error with "exponentiation to negative power";
397 -- X ** 0 is always 1 (including 0 ** 0, so do this test first)
400 return Normalize (One_Data);
402 -- 0 ** X is always 0 (for X non-zero)
405 return Normalize (Zero_Data);
408 -- (-1) ** Y = +/-1 depending on whether Y is even or odd
410 elsif X.Len = 1 and then X.D (1) = 1 then
412 (X.D, Neg => X.Neg and then ((Y.D (Y.Len) and 1) = 1));
414 -- If the absolute value of the base is greater than 1, then the
415 -- exponent must not be bigger than one word, otherwise the result
416 -- is ludicrously large, and we just signal Storage_Error right away.
419 raise Storage_Error with "exponentiation result is too large";
421 -- Special case (+/-)2 ** K, where K is 1 .. 31 using a shift
423 elsif X.Len = 1 and then X.D (1) = 2 and then Y.D (1) < 32 then
425 D : constant Digit_Vector (1 .. 1) :=
426 (1 => Shift_Left (SD'(1), Natural (Y
.D
(1))));
428 return Normalize
(D
, X
.Neg
);
431 -- Remaining cases have right operand of one word
442 function Big_EQ
(X
, Y
: Bignum
) return Boolean is
444 return Compare
(X
.D
, Y
.D
, X
.Neg
, Y
.Neg
) = EQ
;
451 function Big_GE
(X
, Y
: Bignum
) return Boolean is
453 return Compare
(X
.D
, Y
.D
, X
.Neg
, Y
.Neg
) /= LT
;
460 function Big_GT
(X
, Y
: Bignum
) return Boolean is
462 return Compare
(X
.D
, Y
.D
, X
.Neg
, Y
.Neg
) = GT
;
469 function Big_LE
(X
, Y
: Bignum
) return Boolean is
471 return Compare
(X
.D
, Y
.D
, X
.Neg
, Y
.Neg
) /= GT
;
478 function Big_LT
(X
, Y
: Bignum
) return Boolean is
480 return Compare
(X
.D
, Y
.D
, X
.Neg
, Y
.Neg
) = LT
;
487 -- This table is excerpted from RM 4.5.5(28-30) and shows how the result
488 -- of Rem and Mod vary with the signs of the operands.
490 -- A B A mod B A rem B A B A mod B A rem B
492 -- 10 5 0 0 -10 5 0 0
493 -- 11 5 1 1 -11 5 4 -1
494 -- 12 5 2 2 -12 5 3 -2
495 -- 13 5 3 3 -13 5 2 -3
496 -- 14 5 4 4 -14 5 1 -4
498 -- A B A mod B A rem B A B A mod B A rem B
500 -- 10 -5 0 0 -10 -5 0 0
501 -- 11 -5 -4 1 -11 -5 -1 -1
502 -- 12 -5 -3 2 -12 -5 -2 -2
503 -- 13 -5 -2 3 -13 -5 -3 -3
504 -- 14 -5 -1 4 -14 -5 -4 -4
506 function Big_Mod
(X
, Y
: Bignum
) return Bignum
is
510 -- If signs are same, result is same as Rem
512 if X
.Neg
= Y
.Neg
then
513 return Big_Rem
(X
, Y
);
515 -- Case where Mod is different
520 Div_Rem
(X
, Y
, Q
, R
, Discard_Quotient
=> True);
522 -- Zero result is unchanged
527 -- Otherwise adjust result
531 T1
: constant Bignum
:= Big_Sub
(Y
, R
);
545 function Big_Mul
(X
, Y
: Bignum
) return Bignum
is
546 Result
: Digit_Vector
(1 .. X
.Len
+ Y
.Len
) := (others => 0);
547 -- Accumulate result (max length of result is sum of operand lengths)
550 -- Current result digit
556 for J
in 1 .. X
.Len
loop
557 for K
in 1 .. Y
.Len
loop
558 L
:= Result
'Last - (X
.Len
- J
) - (Y
.Len
- K
);
559 D
:= DD
(X
.D
(J
)) * DD
(Y
.D
(K
)) + DD
(Result
(L
));
560 Result
(L
) := LSD
(D
);
563 -- D is carry which must be propagated
565 while D
/= 0 and then L
>= 1 loop
567 D
:= D
+ DD
(Result
(L
));
568 Result
(L
) := LSD
(D
);
572 -- Must not have a carry trying to extend max length
574 pragma Assert
(D
= 0);
580 return Normalize
(Result
, X
.Neg
xor Y
.Neg
);
587 function Big_NE
(X
, Y
: Bignum
) return Boolean is
589 return Compare
(X
.D
, Y
.D
, X
.Neg
, Y
.Neg
) /= EQ
;
596 function Big_Neg
(X
: Bignum
) return Bignum
is
598 return Normalize
(X
.D
, not X
.Neg
);
605 -- This table is excerpted from RM 4.5.5(28-30) and shows how the result
606 -- varies with the signs of the operands.
608 -- A B A rem B A B A rem B
616 -- A B A rem B A B A rem B
624 function Big_Rem
(X
, Y
: Bignum
) return Bignum
is
627 Div_Rem
(X
, Y
, Q
, R
, Discard_Quotient
=> True);
628 R
.Neg
:= R
.Len
> 0 and then X
.Neg
;
636 function Big_Sub
(X
, Y
: Bignum
) return Bignum
is
638 -- If right operand zero, return left operand (avoiding sharing)
641 return Normalize
(X
.D
, X
.Neg
);
643 -- Otherwise add negative of right operand
646 return Add
(X
.D
, Y
.D
, X
.Neg
, not Y
.Neg
);
655 (X
, Y
: Digit_Vector
;
656 X_Neg
, Y_Neg
: Boolean) return Compare_Result
659 -- Signs are different, that's decisive, since 0 is always plus
661 if X_Neg
/= Y_Neg
then
662 return (if X_Neg
then LT
else GT
);
664 -- Lengths are different, that's decisive since no leading zeroes
666 elsif X
'Last /= Y
'Last then
667 return (if (X
'Last > Y
'Last) xor X_Neg
then GT
else LT
);
669 -- Need to compare data
672 for J
in X
'Range loop
673 if X
(J
) /= Y
(J
) then
674 return (if (X
(J
) > Y
(J
)) xor X_Neg
then GT
else LT
);
688 Quotient
: out Bignum
;
689 Remainder
: out Bignum
;
690 Discard_Quotient
: Boolean := False;
691 Discard_Remainder
: Boolean := False)
694 -- Error if division by zero
697 raise Constraint_Error
with "division by zero";
700 -- Handle simple cases with special tests
702 -- If X < Y then quotient is zero and remainder is X
704 if Compare
(X
.D
, Y
.D
, False, False) = LT
then
705 Remainder
:= Normalize
(X
.D
);
706 Quotient
:= Normalize
(Zero_Data
);
709 -- If both X and Y are less than 2**63-1, we can use Long_Long_Integer
710 -- arithmetic. Note it is good not to do an accurate range check against
711 -- Long_Long_Integer since -2**63 / -1 overflows.
713 elsif (X
.Len
<= 1 or else (X
.Len
= 2 and then X
.D
(1) < 2**31))
715 (Y
.Len
<= 1 or else (Y
.Len
= 2 and then Y
.D
(1) < 2**31))
718 A
: constant LLI
:= abs (From_Bignum
(X
));
719 B
: constant LLI
:= abs (From_Bignum
(Y
));
721 Quotient
:= To_Bignum
(A
/ B
);
722 Remainder
:= To_Bignum
(A
rem B
);
726 -- Easy case if divisor is one digit
731 Div
: constant DD
:= DD
(Y
.D
(1));
733 Result
: Digit_Vector
(1 .. X
.Len
);
734 Remdr
: Digit_Vector
(1 .. 1);
738 for J
in 1 .. X
.Len
loop
739 ND
:= Base
* ND
+ DD
(X
.D
(J
));
740 Result
(J
) := SD
(ND
/ Div
);
744 Quotient
:= Normalize
(Result
);
745 Remdr
(1) := SD
(ND
);
746 Remainder
:= Normalize
(Remdr
);
751 -- The complex full multi-precision case. We will employ algorithm
752 -- D defined in the section "The Classical Algorithms" (sec. 4.3.1)
753 -- of Donald Knuth's "The Art of Computer Programming", Vol. 2, 2nd
754 -- edition. The terminology is adjusted for this section to match that
757 -- We are dividing X.Len digits of X (called u here) by Y.Len digits
758 -- of Y (called v here), developing the quotient and remainder. The
759 -- numbers are represented using Base, which was chosen so that we have
760 -- the operations of multiplying to single digits (SD) to form a double
761 -- digit (DD), and dividing a double digit (DD) by a single digit (SD)
762 -- to give a single digit quotient and a single digit remainder.
764 -- Algorithm D from Knuth
766 -- Comments here with square brackets are directly from Knuth
768 Algorithm_D
: declare
770 -- The following lower case variables correspond exactly to the
771 -- terminology used in algorithm D.
773 m
: constant Length
:= X
.Len
- Y
.Len
;
774 n
: constant Length
:= Y
.Len
;
775 b
: constant DD
:= Base
;
777 u
: Digit_Vector
(0 .. m
+ n
);
778 v
: Digit_Vector
(1 .. n
);
779 q
: Digit_Vector
(0 .. m
);
780 r
: Digit_Vector
(1 .. n
);
782 u0
: SD
renames u
(0);
783 v1
: SD
renames v
(1);
784 v2
: SD
renames v
(2);
793 -- Initialize data of left and right operands
795 for J
in 1 .. m
+ n
loop
803 -- [Division of nonnegative integers.] Given nonnegative integers u
804 -- = (ul,u2..um+n) and v = (v1,v2..vn), where v1 /= 0 and n > 1, we
805 -- form the quotient u / v = (q0,ql..qm) and the remainder u mod v =
808 pragma Assert
(v1
/= 0);
809 pragma Assert
(n
> 1);
811 -- Dl. [Normalize.] Set d = b/(vl + 1). Then set (u0,u1,u2..um+n)
812 -- equal to (u1,u2..um+n) times d, and set (v1,v2..vn) equal to
813 -- (v1,v2..vn) times d. Note the introduction of a new digit position
814 -- u0 at the left of u1; if d = 1 all we need to do in this step is
817 d
:= b
/ (DD
(v1
) + 1);
828 -- Multiply Dividend (u) by d
831 for J
in reverse 1 .. m
+ n
loop
832 Tmp
:= DD
(u
(J
)) * d
+ Carry
;
839 -- Multiply Divisor (v) by d
842 for J
in reverse 1 .. n
loop
843 Tmp
:= DD
(v
(J
)) * d
+ Carry
;
848 pragma Assert
(Carry
= 0);
852 -- D2. [Initialize j.] Set j = 0. The loop on j, steps D2 through D7,
853 -- will be essentially a division of (uj, uj+1..uj+n) by (v1,v2..vn)
854 -- to get a single quotient digit qj.
858 -- Loop through digits
861 -- Note: In the original printing, step D3 was as follows:
863 -- D3. [Calculate qhat.] If uj = v1, set qhat to b-l; otherwise
864 -- set qhat to (uj,uj+1)/v1. Now test if v2 * qhat is greater than
865 -- (uj*b + uj+1 - qhat*v1)*b + uj+2. If so, decrease qhat by 1 and
868 -- This had a bug not discovered till 1995, see Vol 2 errata:
869 -- http://www-cs-faculty.stanford.edu/~uno/err2-2e.ps.gz. Under
870 -- rare circumstances the expression in the test could overflow.
871 -- This version was further corrected in 2005, see Vol 2 errata:
872 -- http://www-cs-faculty.stanford.edu/~uno/all2-pre.ps.gz.
873 -- The code below is the fixed version of this step.
875 -- D3. [Calculate qhat.] Set qhat to (uj,uj+1)/v1 and rhat to
876 -- to (uj,uj+1) mod v1.
878 temp
:= u
(j
) & u
(j
+ 1);
879 qhat
:= temp
/ DD
(v1
);
880 rhat
:= temp
mod DD
(v1
);
882 -- D3 (continued). Now test if qhat >= b or v2*qhat > (rhat,uj+2):
883 -- if so, decrease qhat by 1, increase rhat by v1, and repeat this
884 -- test if rhat < b. [The test on v2 determines at high speed
885 -- most of the cases in which the trial value qhat is one too
886 -- large, and eliminates all cases where qhat is two too large.]
889 or else DD
(v2
) * qhat
> LSD
(rhat
) & u
(j
+ 2)
892 rhat
:= rhat
+ DD
(v1
);
896 -- D4. [Multiply and subtract.] Replace (uj,uj+1..uj+n) by
897 -- (uj,uj+1..uj+n) minus qhat times (v1,v2..vn). This step
898 -- consists of a simple multiplication by a one-place number,
899 -- combined with a subtraction.
901 -- The digits (uj,uj+1..uj+n) are always kept positive; if the
902 -- result of this step is actually negative then (uj,uj+1..uj+n)
903 -- is left as the true value plus b**(n+1), i.e. as the b's
904 -- complement of the true value, and a "borrow" to the left is
913 -- Records if subtraction causes a negative result, requiring
914 -- an add back (case where qhat turned out to be 1 too large).
918 for K
in reverse 1 .. n
loop
919 Temp
:= qhat
* DD
(v
(K
)) + DD
(Borrow
);
920 Borrow
:= MSD
(Temp
);
922 if LSD
(Temp
) > u
(j
+ K
) then
923 Borrow
:= Borrow
+ 1;
926 u
(j
+ K
) := u
(j
+ K
) - LSD
(Temp
);
929 Negative
:= u
(j
) < Borrow
;
930 u
(j
) := u
(j
) - Borrow
;
932 -- D5. [Test remainder.] Set qj = qhat. If the result of step
933 -- D4 was negative, we will do the add back step (step D6).
939 -- D6. [Add back.] Decrease qj by 1, and add (0,v1,v2..vn)
940 -- to (uj,uj+1,uj+2..uj+n). (A carry will occur to the left
941 -- of uj, and it is be ignored since it cancels with the
942 -- borrow that occurred in D4.)
947 for K
in reverse 1 .. n
loop
948 Temp
:= DD
(v
(K
)) + DD
(u
(j
+ K
)) + Carry
;
949 u
(j
+ K
) := LSD
(Temp
);
950 Carry
:= Temp
/ Base
;
953 u
(j
) := u
(j
) + SD
(Carry
);
957 -- D7. [Loop on j.] Increase j by one. Now if j <= m, go back to
958 -- D3 (the start of the loop on j).
961 exit when not (j
<= m
);
964 -- D8. [Unnormalize.] Now (qo,ql..qm) is the desired quotient, and
965 -- the desired remainder may be obtained by dividing (um+1..um+n)
968 if not Discard_Quotient
then
969 Quotient
:= Normalize
(q
);
972 if not Discard_Remainder
then
979 Remdr
:= Base
* Remdr
+ DD
(u
(m
+ K
));
980 r
(K
) := SD
(Remdr
/ d
);
981 Remdr
:= Remdr
rem d
;
984 pragma Assert
(Remdr
= 0);
987 Remainder
:= Normalize
(r
);
996 function From_Bignum
(X
: Bignum
) return Long_Long_Integer is
1001 elsif X
.Len
= 1 then
1002 return (if X
.Neg
then -LLI
(X
.D
(1)) else LLI
(X
.D
(1)));
1004 elsif X
.Len
= 2 then
1006 Mag
: constant DD
:= X
.D
(1) & X
.D
(2);
1008 if X
.Neg
and then Mag
<= 2 ** 63 then
1010 elsif Mag
< 2 ** 63 then
1016 raise Constraint_Error
with "expression value out of range";
1019 -------------------------
1020 -- Bignum_In_LLI_Range --
1021 -------------------------
1023 function Bignum_In_LLI_Range
(X
: Bignum
) return Boolean is
1025 -- If length is 0 or 1, definitely fits
1030 -- If length is greater than 2, definitely does not fit
1032 elsif X
.Len
> 2 then
1035 -- Length is 2, more tests needed
1039 Mag
: constant DD
:= X
.D
(1) & X
.D
(2);
1041 return Mag
< 2 ** 63 or else (X
.Neg
and then Mag
= 2 ** 63);
1044 end Bignum_In_LLI_Range
;
1052 Neg
: Boolean := False) return Bignum
1059 while J
<= X
'Last and then X
(J
) = 0 loop
1063 B
:= Allocate_Bignum
(X
'Last - J
+ 1);
1064 B
.Neg
:= B
.Len
> 0 and then Neg
;
1065 B
.D
:= X
(J
.. X
'Last);
1073 function To_Bignum
(X
: Long_Long_Integer) return Bignum
is
1078 R
:= Allocate_Bignum
(0);
1082 elsif X
in -(2 ** 32 - 1) .. +(2 ** 32 - 1) then
1083 R
:= Allocate_Bignum
(1);
1084 R
.D
(1) := SD
(abs (X
));
1086 -- Largest negative number annoyance
1088 elsif X
= Long_Long_Integer'First then
1089 R
:= Allocate_Bignum
(2);
1093 -- Normal two word case
1096 R
:= Allocate_Bignum
(2);
1097 R
.D
(2) := SD
(abs (X
) mod Base
);
1098 R
.D
(1) := SD
(abs (X
) / Base
);