1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2006, 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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 with Output
; use Output
;
35 with Tree_IO
; use Tree_IO
;
37 with GNAT
.HTable
; use GNAT
.HTable
;
41 ------------------------
42 -- Local Declarations --
43 ------------------------
45 Uint_Int_First
: Uint
:= Uint_0
;
46 -- Uint value containing Int'First value, set by Initialize. The initial
47 -- value of Uint_0 is used for an assertion check that ensures that this
48 -- value is not used before it is initialized. This value is used in the
49 -- UI_Is_In_Int_Range predicate, and it is right that this is a host
50 -- value, since the issue is host representation of integer values.
53 -- Uint value containing Int'Last value set by Initialize
55 UI_Power_2
: array (Int
range 0 .. 64) of Uint
;
56 -- This table is used to memoize exponentiations by powers of 2. The Nth
57 -- entry, if set, contains the Uint value 2 ** N. Initially UI_Power_2_Set
58 -- is zero and only the 0'th entry is set, the invariant being that all
59 -- entries in the range 0 .. UI_Power_2_Set are initialized.
62 -- Number of entries set in UI_Power_2;
64 UI_Power_10
: array (Int
range 0 .. 64) of Uint
;
65 -- This table is used to memoize exponentiations by powers of 10 in the
66 -- same manner as described above for UI_Power_2.
68 UI_Power_10_Set
: Nat
;
69 -- Number of entries set in UI_Power_10;
73 -- These values are used to make sure that the mark/release mechanism
74 -- does not destroy values saved in the U_Power tables or in the hash
75 -- table used by UI_From_Int. Whenever an entry is made in either of
76 -- these tabls, Uints_Min and Udigits_Min are updated to protect the
77 -- entry, and Release never cuts back beyond these minimum values.
79 Int_0
: constant Int
:= 0;
80 Int_1
: constant Int
:= 1;
81 Int_2
: constant Int
:= 2;
82 -- These values are used in some cases where the use of numeric literals
83 -- would cause ambiguities (integer vs Uint).
85 ----------------------------
86 -- UI_From_Int Hash Table --
87 ----------------------------
89 -- UI_From_Int uses a hash table to avoid duplicating entries and
90 -- wasting storage. This is particularly important for complex cases
91 -- of back annotation.
93 subtype Hnum
is Nat
range 0 .. 1022;
95 function Hash_Num
(F
: Int
) return Hnum
;
98 package UI_Ints
is new Simple_HTable
(
101 No_Element
=> No_Uint
,
106 -----------------------
107 -- Local Subprograms --
108 -----------------------
110 function Direct
(U
: Uint
) return Boolean;
111 pragma Inline
(Direct
);
112 -- Returns True if U is represented directly
114 function Direct_Val
(U
: Uint
) return Int
;
115 -- U is a Uint for is represented directly. The returned result
116 -- is the value represented.
118 function GCD
(Jin
, Kin
: Int
) return Int
;
119 -- Compute GCD of two integers. Assumes that Jin >= Kin >= 0
125 -- Common processing for UI_Image and UI_Write, To_Buffer is set
126 -- True for UI_Image, and false for UI_Write, and Format is copied
127 -- from the Format parameter to UI_Image or UI_Write.
129 procedure Init_Operand
(UI
: Uint
; Vec
: out UI_Vector
);
130 pragma Inline
(Init_Operand
);
131 -- This procedure puts the value of UI into the vector in canonical
132 -- multiple precision format. The parameter should be of the correct
133 -- size as determined by a previous call to N_Digits (UI). The first
134 -- digit of Vec contains the sign, all other digits are always non-
135 -- negative. Note that the input may be directly represented, and in
136 -- this case Vec will contain the corresponding one or two digit value.
137 -- The low bound of Vec is always 1.
139 function Least_Sig_Digit
(Arg
: Uint
) return Int
;
140 pragma Inline
(Least_Sig_Digit
);
141 -- Returns the Least Significant Digit of Arg quickly. When the given
142 -- Uint is less than 2**15, the value returned is the input value, in
143 -- this case the result may be negative. It is expected that any use
144 -- will mask off unnecessary bits. This is used for finding Arg mod B
145 -- where B is a power of two. Hence the actual base is irrelevent as
146 -- long as it is a power of two.
148 procedure Most_Sig_2_Digits
152 Right_Hat
: out Int
);
153 -- Returns leading two significant digits from the given pair of Uint's.
154 -- Mathematically: returns Left / (Base ** K) and Right / (Base ** K)
155 -- where K is as small as possible S.T. Right_Hat < Base * Base.
156 -- It is required that Left > Right for the algorithm to work.
158 function N_Digits
(Input
: Uint
) return Int
;
159 pragma Inline
(N_Digits
);
160 -- Returns number of "digits" in a Uint
162 function Sum_Digits
(Left
: Uint
; Sign
: Int
) return Int
;
163 -- If Sign = 1 return the sum of the "digits" of Abs (Left). If the
164 -- total has more then one digit then return Sum_Digits of total.
166 function Sum_Double_Digits
(Left
: Uint
; Sign
: Int
) return Int
;
167 -- Same as above but work in New_Base = Base * Base
169 function Vector_To_Uint
173 -- Functions that calculate values in UI_Vectors, call this function
174 -- to create and return the Uint value. In_Vec contains the multiple
175 -- precision (Base) representation of a non-negative value. Leading
176 -- zeroes are permitted. Negative is set if the desired result is
177 -- the negative of the given value. The result will be either the
178 -- appropriate directly represented value, or a table entry in the
179 -- proper canonical format is created and returned.
181 -- Note that Init_Operand puts a signed value in the result vector,
182 -- but Vector_To_Uint is always presented with a non-negative value.
183 -- The processing of signs is something that is done by the caller
184 -- before calling Vector_To_Uint.
190 function Direct
(U
: Uint
) return Boolean is
192 return Int
(U
) <= Int
(Uint_Direct_Last
);
199 function Direct_Val
(U
: Uint
) return Int
is
201 pragma Assert
(Direct
(U
));
202 return Int
(U
) - Int
(Uint_Direct_Bias
);
209 function GCD
(Jin
, Kin
: Int
) return Int
is
213 pragma Assert
(Jin
>= Kin
);
214 pragma Assert
(Kin
>= Int_0
);
219 while K
/= Uint_0
loop
232 function Hash_Num
(F
: Int
) return Hnum
is
234 return Standard
."mod" (F
, Hnum
'Range_Length);
246 Marks
: constant Uintp
.Save_Mark
:= Uintp
.Mark
;
250 Digs_Output
: Natural := 0;
251 -- Counts digits output. In hex mode, but not in decimal mode, we
252 -- put an underline after every four hex digits that are output.
254 Exponent
: Natural := 0;
255 -- If the number is too long to fit in the buffer, we switch to an
256 -- approximate output format with an exponent. This variable records
257 -- the exponent value.
259 function Better_In_Hex
return Boolean;
260 -- Determines if it is better to generate digits in base 16 (result
261 -- is true) or base 10 (result is false). The choice is purely a
262 -- matter of convenience and aesthetics, so it does not matter which
263 -- value is returned from a correctness point of view.
265 procedure Image_Char
(C
: Character);
266 -- Internal procedure to output one character
268 procedure Image_Exponent
(N
: Natural);
269 -- Output non-zero exponent. Note that we only use the exponent
270 -- form in the buffer case, so we know that To_Buffer is true.
272 procedure Image_Uint
(U
: Uint
);
273 -- Internal procedure to output characters of non-negative Uint
279 function Better_In_Hex
return Boolean is
280 T16
: constant Uint
:= Uint_2
** Int
'(16);
286 -- Small values up to 2**16 can always be in decimal
292 -- Otherwise, see if we are a power of 2 or one less than a power
293 -- of 2. For the moment these are the only cases printed in hex.
295 if A mod Uint_2 = Uint_1 then
300 if A mod T16 /= Uint_0 then
310 while A > Uint_2 loop
311 if A mod Uint_2 /= Uint_0 then
326 procedure Image_Char (C : Character) is
329 if UI_Image_Length + 6 > UI_Image_Max then
330 Exponent := Exponent + 1;
332 UI_Image_Length := UI_Image_Length + 1;
333 UI_Image_Buffer (UI_Image_Length) := C;
344 procedure Image_Exponent (N : Natural) is
347 Image_Exponent (N / 10);
350 UI_Image_Length := UI_Image_Length + 1;
351 UI_Image_Buffer (UI_Image_Length) :=
352 Character'Val (Character'Pos ('0') + N mod 10);
359 procedure Image_Uint (U : Uint) is
360 H : constant array (Int range 0 .. 15) of Character :=
365 Image_Uint (U / Base);
368 if Digs_Output = 4 and then Base = Uint_16 then
373 Image_Char (H (UI_To_Int (U rem Base)));
375 Digs_Output := Digs_Output + 1;
378 -- Start of processing for Image_Out
381 if Input = No_Uint then
386 UI_Image_Length := 0;
388 if Input < Uint_0 then
396 or else (Format = Auto and then Better_In_Hex)
410 if Exponent /= 0 then
411 UI_Image_Length := UI_Image_Length + 1;
412 UI_Image_Buffer (UI_Image_Length) := 'E
';
413 Image_Exponent (Exponent);
416 Uintp.Release (Marks);
423 procedure Init_Operand (UI : Uint; Vec : out UI_Vector) is
426 pragma Assert (Vec'First = Int'(1));
430 Vec
(1) := Direct_Val
(UI
);
432 if Vec
(1) >= Base
then
433 Vec
(2) := Vec
(1) rem Base
;
434 Vec
(1) := Vec
(1) / Base
;
438 Loc
:= Uints
.Table
(UI
).Loc
;
440 for J
in 1 .. Uints
.Table
(UI
).Length
loop
441 Vec
(J
) := Udigits
.Table
(Loc
+ J
- 1);
450 procedure Initialize
is
455 Uint_Int_First
:= UI_From_Int
(Int
'First);
456 Uint_Int_Last
:= UI_From_Int
(Int
'Last);
458 UI_Power_2
(0) := Uint_1
;
461 UI_Power_10
(0) := Uint_1
;
462 UI_Power_10_Set
:= 0;
464 Uints_Min
:= Uints
.Last
;
465 Udigits_Min
:= Udigits
.Last
;
470 ---------------------
471 -- Least_Sig_Digit --
472 ---------------------
474 function Least_Sig_Digit
(Arg
: Uint
) return Int
is
479 V
:= Direct_Val
(Arg
);
485 -- Note that this result may be negative
492 (Uints
.Table
(Arg
).Loc
+ Uints
.Table
(Arg
).Length
- 1);
500 function Mark
return Save_Mark
is
502 return (Save_Uint
=> Uints
.Last
, Save_Udigit
=> Udigits
.Last
);
505 -----------------------
506 -- Most_Sig_2_Digits --
507 -----------------------
509 procedure Most_Sig_2_Digits
516 pragma Assert
(Left
>= Right
);
518 if Direct
(Left
) then
519 Left_Hat
:= Direct_Val
(Left
);
520 Right_Hat
:= Direct_Val
(Right
);
526 Udigits
.Table
(Uints
.Table
(Left
).Loc
);
528 Udigits
.Table
(Uints
.Table
(Left
).Loc
+ 1);
531 -- It is not so clear what to return when Arg is negative???
533 Left_Hat
:= abs (L1
) * Base
+ L2
;
538 Length_L
: constant Int
:= Uints
.Table
(Left
).Length
;
545 if Direct
(Right
) then
546 T
:= Direct_Val
(Left
);
547 R1
:= abs (T
/ Base
);
552 R1
:= abs (Udigits
.Table
(Uints
.Table
(Right
).Loc
));
553 R2
:= Udigits
.Table
(Uints
.Table
(Right
).Loc
+ 1);
554 Length_R
:= Uints
.Table
(Right
).Length
;
557 if Length_L
= Length_R
then
558 Right_Hat
:= R1
* Base
+ R2
;
559 elsif Length_L
= Length_R
+ Int_1
then
565 end Most_Sig_2_Digits
;
571 -- Note: N_Digits returns 1 for No_Uint
573 function N_Digits
(Input
: Uint
) return Int
is
575 if Direct
(Input
) then
576 if Direct_Val
(Input
) >= Base
then
583 return Uints
.Table
(Input
).Length
;
591 function Num_Bits
(Input
: Uint
) return Nat
is
596 -- Largest negative number has to be handled specially, since it is in
597 -- Int_Range, but we cannot take the absolute value.
599 if Input
= Uint_Int_First
then
602 -- For any other number in Int_Range, get absolute value of number
604 elsif UI_Is_In_Int_Range
(Input
) then
605 Num
:= abs (UI_To_Int
(Input
));
608 -- If not in Int_Range then initialize bit count for all low order
609 -- words, and set number to high order digit.
612 Bits
:= Base_Bits
* (Uints
.Table
(Input
).Length
- 1);
613 Num
:= abs (Udigits
.Table
(Uints
.Table
(Input
).Loc
));
616 -- Increase bit count for remaining value in Num
618 while Types
.">" (Num
, 0) loop
630 procedure pid
(Input
: Uint
) is
632 UI_Write
(Input
, Decimal
);
640 procedure pih
(Input
: Uint
) is
642 UI_Write
(Input
, Hex
);
650 procedure Release
(M
: Save_Mark
) is
652 Uints
.Set_Last
(Uint
'Max (M
.Save_Uint
, Uints_Min
));
653 Udigits
.Set_Last
(Int
'Max (M
.Save_Udigit
, Udigits_Min
));
656 ----------------------
657 -- Release_And_Save --
658 ----------------------
660 procedure Release_And_Save
(M
: Save_Mark
; UI
: in out Uint
) is
667 UE_Len
: constant Pos
:= Uints
.Table
(UI
).Length
;
668 UE_Loc
: constant Int
:= Uints
.Table
(UI
).Loc
;
670 UD
: constant Udigits
.Table_Type
(1 .. UE_Len
) :=
671 Udigits
.Table
(UE_Loc
.. UE_Loc
+ UE_Len
- 1);
676 Uints
.Increment_Last
;
679 Uints
.Table
(UI
) := (UE_Len
, Udigits
.Last
+ 1);
681 for J
in 1 .. UE_Len
loop
682 Udigits
.Increment_Last
;
683 Udigits
.Table
(Udigits
.Last
) := UD
(J
);
687 end Release_And_Save
;
689 procedure Release_And_Save
(M
: Save_Mark
; UI1
, UI2
: in out Uint
) is
692 Release_And_Save
(M
, UI2
);
694 elsif Direct
(UI2
) then
695 Release_And_Save
(M
, UI1
);
699 UE1_Len
: constant Pos
:= Uints
.Table
(UI1
).Length
;
700 UE1_Loc
: constant Int
:= Uints
.Table
(UI1
).Loc
;
702 UD1
: constant Udigits
.Table_Type
(1 .. UE1_Len
) :=
703 Udigits
.Table
(UE1_Loc
.. UE1_Loc
+ UE1_Len
- 1);
705 UE2_Len
: constant Pos
:= Uints
.Table
(UI2
).Length
;
706 UE2_Loc
: constant Int
:= Uints
.Table
(UI2
).Loc
;
708 UD2
: constant Udigits
.Table_Type
(1 .. UE2_Len
) :=
709 Udigits
.Table
(UE2_Loc
.. UE2_Loc
+ UE2_Len
- 1);
714 Uints
.Increment_Last
;
717 Uints
.Table
(UI1
) := (UE1_Len
, Udigits
.Last
+ 1);
719 for J
in 1 .. UE1_Len
loop
720 Udigits
.Increment_Last
;
721 Udigits
.Table
(Udigits
.Last
) := UD1
(J
);
724 Uints
.Increment_Last
;
727 Uints
.Table
(UI2
) := (UE2_Len
, Udigits
.Last
+ 1);
729 for J
in 1 .. UE2_Len
loop
730 Udigits
.Increment_Last
;
731 Udigits
.Table
(Udigits
.Last
) := UD2
(J
);
735 end Release_And_Save
;
741 -- This is done in one pass
743 -- Mathematically: assume base congruent to 1 and compute an equivelent
746 -- If Sign = -1 return the alternating sum of the "digits"
748 -- D1 - D2 + D3 - D4 + D5 ...
750 -- (where D1 is Least Significant Digit)
752 -- Mathematically: assume base congruent to -1 and compute an equivelent
755 -- This is used in Rem and Base is assumed to be 2 ** 15
757 -- Note: The next two functions are very similar, any style changes made
758 -- to one should be reflected in both. These would be simpler if we
759 -- worked base 2 ** 32.
761 function Sum_Digits
(Left
: Uint
; Sign
: Int
) return Int
is
763 pragma Assert
(Sign
= Int_1
or Sign
= Int
(-1));
765 -- First try simple case;
767 if Direct
(Left
) then
769 Tmp_Int
: Int
:= Direct_Val
(Left
);
772 if Tmp_Int
>= Base
then
773 Tmp_Int
:= (Tmp_Int
/ Base
) +
774 Sign
* (Tmp_Int
rem Base
);
776 -- Now Tmp_Int is in [-(Base - 1) .. 2 * (Base - 1)]
778 if Tmp_Int
>= Base
then
782 Tmp_Int
:= (Tmp_Int
/ Base
) + 1;
786 -- Now Tmp_Int is in [-(Base - 1) .. (Base - 1)]
793 -- Otherwise full circuit is needed
797 L_Length
: constant Int
:= N_Digits
(Left
);
798 L_Vec
: UI_Vector
(1 .. L_Length
);
804 Init_Operand
(Left
, L_Vec
);
805 L_Vec
(1) := abs L_Vec
(1);
810 for J
in reverse 1 .. L_Length
loop
811 Tmp_Int
:= Tmp_Int
+ Alt
* (L_Vec
(J
) + Carry
);
813 -- Tmp_Int is now between [-2 * Base + 1 .. 2 * Base - 1],
814 -- since old Tmp_Int is between [-(Base - 1) .. Base - 1]
815 -- and L_Vec is in [0 .. Base - 1] and Carry in [-1 .. 1]
817 if Tmp_Int
>= Base
then
818 Tmp_Int
:= Tmp_Int
- Base
;
821 elsif Tmp_Int
<= -Base
then
822 Tmp_Int
:= Tmp_Int
+ Base
;
829 -- Tmp_Int is now between [-Base + 1 .. Base - 1]
834 Tmp_Int
:= Tmp_Int
+ Alt
* Carry
;
836 -- Tmp_Int is now between [-Base .. Base]
838 if Tmp_Int
>= Base
then
839 Tmp_Int
:= Tmp_Int
- Base
+ Alt
* Sign
* 1;
841 elsif Tmp_Int
<= -Base
then
842 Tmp_Int
:= Tmp_Int
+ Base
+ Alt
* Sign
* (-1);
845 -- Now Tmp_Int is in [-(Base - 1) .. (Base - 1)]
852 -----------------------
853 -- Sum_Double_Digits --
854 -----------------------
856 -- Note: This is used in Rem, Base is assumed to be 2 ** 15
858 function Sum_Double_Digits
(Left
: Uint
; Sign
: Int
) return Int
is
860 -- First try simple case;
862 pragma Assert
(Sign
= Int_1
or Sign
= Int
(-1));
864 if Direct
(Left
) then
865 return Direct_Val
(Left
);
867 -- Otherwise full circuit is needed
871 L_Length
: constant Int
:= N_Digits
(Left
);
872 L_Vec
: UI_Vector
(1 .. L_Length
);
880 Init_Operand
(Left
, L_Vec
);
881 L_Vec
(1) := abs L_Vec
(1);
889 Least_Sig_Int
:= Least_Sig_Int
+ Alt
* (L_Vec
(J
) + Carry
);
891 -- Least is in [-2 Base + 1 .. 2 * Base - 1]
892 -- Since L_Vec in [0 .. Base - 1] and Carry in [-1 .. 1]
893 -- and old Least in [-Base + 1 .. Base - 1]
895 if Least_Sig_Int
>= Base
then
896 Least_Sig_Int
:= Least_Sig_Int
- Base
;
899 elsif Least_Sig_Int
<= -Base
then
900 Least_Sig_Int
:= Least_Sig_Int
+ Base
;
907 -- Least is now in [-Base + 1 .. Base - 1]
909 Most_Sig_Int
:= Most_Sig_Int
+ Alt
* (L_Vec
(J
- 1) + Carry
);
911 -- Most is in [-2 Base + 1 .. 2 * Base - 1]
912 -- Since L_Vec in [0 .. Base - 1] and Carry in [-1 .. 1]
913 -- and old Most in [-Base + 1 .. Base - 1]
915 if Most_Sig_Int
>= Base
then
916 Most_Sig_Int
:= Most_Sig_Int
- Base
;
919 elsif Most_Sig_Int
<= -Base
then
920 Most_Sig_Int
:= Most_Sig_Int
+ Base
;
926 -- Most is now in [-Base + 1 .. Base - 1]
933 Least_Sig_Int
:= Least_Sig_Int
+ Alt
* (L_Vec
(J
) + Carry
);
935 Least_Sig_Int
:= Least_Sig_Int
+ Alt
* Carry
;
938 if Least_Sig_Int
>= Base
then
939 Least_Sig_Int
:= Least_Sig_Int
- Base
;
940 Most_Sig_Int
:= Most_Sig_Int
+ Alt
* 1;
942 elsif Least_Sig_Int
<= -Base
then
943 Least_Sig_Int
:= Least_Sig_Int
+ Base
;
944 Most_Sig_Int
:= Most_Sig_Int
+ Alt
* (-1);
947 if Most_Sig_Int
>= Base
then
948 Most_Sig_Int
:= Most_Sig_Int
- Base
;
951 Least_Sig_Int
+ Alt
* 1; -- cannot overflow again
953 elsif Most_Sig_Int
<= -Base
then
954 Most_Sig_Int
:= Most_Sig_Int
+ Base
;
957 Least_Sig_Int
+ Alt
* (-1); -- cannot overflow again.
960 return Most_Sig_Int
* Base
+ Least_Sig_Int
;
963 end Sum_Double_Digits
;
969 procedure Tree_Read
is
974 Tree_Read_Int
(Int
(Uint_Int_First
));
975 Tree_Read_Int
(Int
(Uint_Int_Last
));
976 Tree_Read_Int
(UI_Power_2_Set
);
977 Tree_Read_Int
(UI_Power_10_Set
);
978 Tree_Read_Int
(Int
(Uints_Min
));
979 Tree_Read_Int
(Udigits_Min
);
981 for J
in 0 .. UI_Power_2_Set
loop
982 Tree_Read_Int
(Int
(UI_Power_2
(J
)));
985 for J
in 0 .. UI_Power_10_Set
loop
986 Tree_Read_Int
(Int
(UI_Power_10
(J
)));
995 procedure Tree_Write
is
1000 Tree_Write_Int
(Int
(Uint_Int_First
));
1001 Tree_Write_Int
(Int
(Uint_Int_Last
));
1002 Tree_Write_Int
(UI_Power_2_Set
);
1003 Tree_Write_Int
(UI_Power_10_Set
);
1004 Tree_Write_Int
(Int
(Uints_Min
));
1005 Tree_Write_Int
(Udigits_Min
);
1007 for J
in 0 .. UI_Power_2_Set
loop
1008 Tree_Write_Int
(Int
(UI_Power_2
(J
)));
1011 for J
in 0 .. UI_Power_10_Set
loop
1012 Tree_Write_Int
(Int
(UI_Power_10
(J
)));
1021 function UI_Abs
(Right
: Uint
) return Uint
is
1023 if Right
< Uint_0
then
1034 function UI_Add
(Left
: Int
; Right
: Uint
) return Uint
is
1036 return UI_Add
(UI_From_Int
(Left
), Right
);
1039 function UI_Add
(Left
: Uint
; Right
: Int
) return Uint
is
1041 return UI_Add
(Left
, UI_From_Int
(Right
));
1044 function UI_Add
(Left
: Uint
; Right
: Uint
) return Uint
is
1046 -- Simple cases of direct operands and addition of zero
1048 if Direct
(Left
) then
1049 if Direct
(Right
) then
1050 return UI_From_Int
(Direct_Val
(Left
) + Direct_Val
(Right
));
1052 elsif Int
(Left
) = Int
(Uint_0
) then
1056 elsif Direct
(Right
) and then Int
(Right
) = Int
(Uint_0
) then
1060 -- Otherwise full circuit is needed
1063 L_Length
: constant Int
:= N_Digits
(Left
);
1064 R_Length
: constant Int
:= N_Digits
(Right
);
1065 L_Vec
: UI_Vector
(1 .. L_Length
);
1066 R_Vec
: UI_Vector
(1 .. R_Length
);
1071 X_Bigger
: Boolean := False;
1072 Y_Bigger
: Boolean := False;
1073 Result_Neg
: Boolean := False;
1076 Init_Operand
(Left
, L_Vec
);
1077 Init_Operand
(Right
, R_Vec
);
1079 -- At least one of the two operands is in multi-digit form.
1080 -- Calculate the number of digits sufficient to hold result.
1082 if L_Length
> R_Length
then
1083 Sum_Length
:= L_Length
+ 1;
1086 Sum_Length
:= R_Length
+ 1;
1087 if R_Length
> L_Length
then Y_Bigger
:= True; end if;
1090 -- Make copies of the absolute values of L_Vec and R_Vec into
1091 -- X and Y both with lengths equal to the maximum possibly
1092 -- needed. This makes looping over the digits much simpler.
1095 X
: UI_Vector
(1 .. Sum_Length
);
1096 Y
: UI_Vector
(1 .. Sum_Length
);
1097 Tmp_UI
: UI_Vector
(1 .. Sum_Length
);
1100 for J
in 1 .. Sum_Length
- L_Length
loop
1104 X
(Sum_Length
- L_Length
+ 1) := abs L_Vec
(1);
1106 for J
in 2 .. L_Length
loop
1107 X
(J
+ (Sum_Length
- L_Length
)) := L_Vec
(J
);
1110 for J
in 1 .. Sum_Length
- R_Length
loop
1114 Y
(Sum_Length
- R_Length
+ 1) := abs R_Vec
(1);
1116 for J
in 2 .. R_Length
loop
1117 Y
(J
+ (Sum_Length
- R_Length
)) := R_Vec
(J
);
1120 if (L_Vec
(1) < Int_0
) = (R_Vec
(1) < Int_0
) then
1122 -- Same sign so just add
1125 for J
in reverse 1 .. Sum_Length
loop
1126 Tmp_Int
:= X
(J
) + Y
(J
) + Carry
;
1128 if Tmp_Int
>= Base
then
1129 Tmp_Int
:= Tmp_Int
- Base
;
1138 return Vector_To_Uint
(X
, L_Vec
(1) < Int_0
);
1141 -- Find which one has bigger magnitude
1143 if not (X_Bigger
or Y_Bigger
) then
1144 for J
in L_Vec
'Range loop
1145 if abs L_Vec
(J
) > abs R_Vec
(J
) then
1148 elsif abs R_Vec
(J
) > abs L_Vec
(J
) then
1155 -- If they have identical magnitude, just return 0, else
1156 -- swap if necessary so that X had the bigger magnitude.
1157 -- Determine if result is negative at this time.
1159 Result_Neg
:= False;
1161 if not (X_Bigger
or Y_Bigger
) then
1165 if R_Vec
(1) < Int_0
then
1174 if L_Vec
(1) < Int_0
then
1179 -- Subtract Y from the bigger X
1183 for J
in reverse 1 .. Sum_Length
loop
1184 Tmp_Int
:= X
(J
) - Y
(J
) + Borrow
;
1186 if Tmp_Int
< Int_0
then
1187 Tmp_Int
:= Tmp_Int
+ Base
;
1196 return Vector_To_Uint
(X
, Result_Neg
);
1203 --------------------------
1204 -- UI_Decimal_Digits_Hi --
1205 --------------------------
1207 function UI_Decimal_Digits_Hi
(U
: Uint
) return Nat
is
1209 -- The maximum value of a "digit" is 32767, which is 5 decimal
1210 -- digits, so an N_Digit number could take up to 5 times this
1211 -- number of digits. This is certainly too high for large
1212 -- numbers but it is not worth worrying about.
1214 return 5 * N_Digits
(U
);
1215 end UI_Decimal_Digits_Hi
;
1217 --------------------------
1218 -- UI_Decimal_Digits_Lo --
1219 --------------------------
1221 function UI_Decimal_Digits_Lo
(U
: Uint
) return Nat
is
1223 -- The maximum value of a "digit" is 32767, which is more than four
1224 -- decimal digits, but not a full five digits. The easily computed
1225 -- minimum number of decimal digits is thus 1 + 4 * the number of
1226 -- digits. This is certainly too low for large numbers but it is
1227 -- not worth worrying about.
1229 return 1 + 4 * (N_Digits
(U
) - 1);
1230 end UI_Decimal_Digits_Lo
;
1236 function UI_Div
(Left
: Int
; Right
: Uint
) return Uint
is
1238 return UI_Div
(UI_From_Int
(Left
), Right
);
1241 function UI_Div
(Left
: Uint
; Right
: Int
) return Uint
is
1243 return UI_Div
(Left
, UI_From_Int
(Right
));
1246 function UI_Div
(Left
, Right
: Uint
) return Uint
is
1248 pragma Assert
(Right
/= Uint_0
);
1250 -- Cases where both operands are represented directly
1252 if Direct
(Left
) and then Direct
(Right
) then
1253 return UI_From_Int
(Direct_Val
(Left
) / Direct_Val
(Right
));
1257 L_Length
: constant Int
:= N_Digits
(Left
);
1258 R_Length
: constant Int
:= N_Digits
(Right
);
1259 Q_Length
: constant Int
:= L_Length
- R_Length
+ 1;
1260 L_Vec
: UI_Vector
(1 .. L_Length
);
1261 R_Vec
: UI_Vector
(1 .. R_Length
);
1270 -- Result is zero if left operand is shorter than right
1272 if L_Length
< R_Length
then
1276 Init_Operand
(Left
, L_Vec
);
1277 Init_Operand
(Right
, R_Vec
);
1279 -- Case of right operand is single digit. Here we can simply divide
1280 -- each digit of the left operand by the divisor, from most to least
1281 -- significant, carrying the remainder to the next digit (just like
1282 -- ordinary long division by hand).
1284 if R_Length
= Int_1
then
1286 Tmp_Divisor
:= abs R_Vec
(1);
1289 Quotient
: UI_Vector
(1 .. L_Length
);
1292 for J
in L_Vec
'Range loop
1293 Tmp_Int
:= Remainder
* Base
+ abs L_Vec
(J
);
1294 Quotient
(J
) := Tmp_Int
/ Tmp_Divisor
;
1295 Remainder
:= Tmp_Int
rem Tmp_Divisor
;
1300 (Quotient
, (L_Vec
(1) < Int_0
xor R_Vec
(1) < Int_0
));
1304 -- The possible simple cases have been exhausted. Now turn to the
1305 -- algorithm D from the section of Knuth mentioned at the top of
1308 Algorithm_D
: declare
1309 Dividend
: UI_Vector
(1 .. L_Length
+ 1);
1310 Divisor
: UI_Vector
(1 .. R_Length
);
1311 Quotient
: UI_Vector
(1 .. Q_Length
);
1317 -- [ NORMALIZE ] (step D1 in the algorithm). First calculate the
1318 -- scale d, and then multiply Left and Right (u and v in the book)
1319 -- by d to get the dividend and divisor to work with.
1321 D
:= Base
/ (abs R_Vec
(1) + 1);
1324 Dividend
(2) := abs L_Vec
(1);
1326 for J
in 3 .. L_Length
+ Int_1
loop
1327 Dividend
(J
) := L_Vec
(J
- 1);
1330 Divisor
(1) := abs R_Vec
(1);
1332 for J
in Int_2
.. R_Length
loop
1333 Divisor
(J
) := R_Vec
(J
);
1338 -- Multiply Dividend by D
1341 for J
in reverse Dividend
'Range loop
1342 Tmp_Int
:= Dividend
(J
) * D
+ Carry
;
1343 Dividend
(J
) := Tmp_Int
rem Base
;
1344 Carry
:= Tmp_Int
/ Base
;
1347 -- Multiply Divisor by d
1350 for J
in reverse Divisor
'Range loop
1351 Tmp_Int
:= Divisor
(J
) * D
+ Carry
;
1352 Divisor
(J
) := Tmp_Int
rem Base
;
1353 Carry
:= Tmp_Int
/ Base
;
1357 -- Main loop of long division algorithm
1359 Divisor_Dig1
:= Divisor
(1);
1360 Divisor_Dig2
:= Divisor
(2);
1362 for J
in Quotient
'Range loop
1364 -- [ CALCULATE Q (hat) ] (step D3 in the algorithm)
1366 Tmp_Int
:= Dividend
(J
) * Base
+ Dividend
(J
+ 1);
1370 if Dividend
(J
) = Divisor_Dig1
then
1371 Q_Guess
:= Base
- 1;
1373 Q_Guess
:= Tmp_Int
/ Divisor_Dig1
;
1378 while Divisor_Dig2
* Q_Guess
>
1379 (Tmp_Int
- Q_Guess
* Divisor_Dig1
) * Base
+
1382 Q_Guess
:= Q_Guess
- 1;
1385 -- [ MULTIPLY & SUBTRACT] (step D4). Q_Guess * Divisor is
1386 -- subtracted from the remaining dividend.
1389 for K
in reverse Divisor
'Range loop
1390 Tmp_Int
:= Dividend
(J
+ K
) - Q_Guess
* Divisor
(K
) + Carry
;
1391 Tmp_Dig
:= Tmp_Int
rem Base
;
1392 Carry
:= Tmp_Int
/ Base
;
1394 if Tmp_Dig
< Int_0
then
1395 Tmp_Dig
:= Tmp_Dig
+ Base
;
1399 Dividend
(J
+ K
) := Tmp_Dig
;
1402 Dividend
(J
) := Dividend
(J
) + Carry
;
1404 -- [ TEST REMAINDER ] & [ ADD BACK ] (steps D5 and D6)
1405 -- Here there is a slight difference from the book: the last
1406 -- carry is always added in above and below (cancelling each
1407 -- other). In fact the dividend going negative is used as
1410 -- If the Dividend went negative, then Q_Guess was off by
1411 -- one, so it is decremented, and the divisor is added back
1412 -- into the relevant portion of the dividend.
1414 if Dividend
(J
) < Int_0
then
1415 Q_Guess
:= Q_Guess
- 1;
1418 for K
in reverse Divisor
'Range loop
1419 Tmp_Int
:= Dividend
(J
+ K
) + Divisor
(K
) + Carry
;
1421 if Tmp_Int
>= Base
then
1422 Tmp_Int
:= Tmp_Int
- Base
;
1428 Dividend
(J
+ K
) := Tmp_Int
;
1431 Dividend
(J
) := Dividend
(J
) + Carry
;
1434 -- Finally we can get the next quotient digit
1436 Quotient
(J
) := Q_Guess
;
1439 return Vector_To_Uint
1440 (Quotient
, (L_Vec
(1) < Int_0
xor R_Vec
(1) < Int_0
));
1450 function UI_Eq
(Left
: Int
; Right
: Uint
) return Boolean is
1452 return not UI_Ne
(UI_From_Int
(Left
), Right
);
1455 function UI_Eq
(Left
: Uint
; Right
: Int
) return Boolean is
1457 return not UI_Ne
(Left
, UI_From_Int
(Right
));
1460 function UI_Eq
(Left
: Uint
; Right
: Uint
) return Boolean is
1462 return not UI_Ne
(Left
, Right
);
1469 function UI_Expon
(Left
: Int
; Right
: Uint
) return Uint
is
1471 return UI_Expon
(UI_From_Int
(Left
), Right
);
1474 function UI_Expon
(Left
: Uint
; Right
: Int
) return Uint
is
1476 return UI_Expon
(Left
, UI_From_Int
(Right
));
1479 function UI_Expon
(Left
: Int
; Right
: Int
) return Uint
is
1481 return UI_Expon
(UI_From_Int
(Left
), UI_From_Int
(Right
));
1484 function UI_Expon
(Left
: Uint
; Right
: Uint
) return Uint
is
1486 pragma Assert
(Right
>= Uint_0
);
1488 -- Any value raised to power of 0 is 1
1490 if Right
= Uint_0
then
1493 -- 0 to any positive power is 0
1495 elsif Left
= Uint_0
then
1498 -- 1 to any power is 1
1500 elsif Left
= Uint_1
then
1503 -- Any value raised to power of 1 is that value
1505 elsif Right
= Uint_1
then
1508 -- Cases which can be done by table lookup
1510 elsif Right
<= Uint_64
then
1512 -- 2 ** N for N in 2 .. 64
1514 if Left
= Uint_2
then
1516 Right_Int
: constant Int
:= Direct_Val
(Right
);
1519 if Right_Int
> UI_Power_2_Set
then
1520 for J
in UI_Power_2_Set
+ Int_1
.. Right_Int
loop
1521 UI_Power_2
(J
) := UI_Power_2
(J
- Int_1
) * Int_2
;
1522 Uints_Min
:= Uints
.Last
;
1523 Udigits_Min
:= Udigits
.Last
;
1526 UI_Power_2_Set
:= Right_Int
;
1529 return UI_Power_2
(Right_Int
);
1532 -- 10 ** N for N in 2 .. 64
1534 elsif Left
= Uint_10
then
1536 Right_Int
: constant Int
:= Direct_Val
(Right
);
1539 if Right_Int
> UI_Power_10_Set
then
1540 for J
in UI_Power_10_Set
+ Int_1
.. Right_Int
loop
1541 UI_Power_10
(J
) := UI_Power_10
(J
- Int_1
) * Int
(10);
1542 Uints_Min
:= Uints
.Last
;
1543 Udigits_Min
:= Udigits
.Last
;
1546 UI_Power_10_Set
:= Right_Int
;
1549 return UI_Power_10
(Right_Int
);
1554 -- If we fall through, then we have the general case (see Knuth 4.6.3)
1558 Squares
: Uint
:= Left
;
1559 Result
: Uint
:= Uint_1
;
1560 M
: constant Uintp
.Save_Mark
:= Uintp
.Mark
;
1564 if (Least_Sig_Digit
(N
) mod Int_2
) = Int_1
then
1565 Result
:= Result
* Squares
;
1569 exit when N
= Uint_0
;
1570 Squares
:= Squares
* Squares
;
1573 Uintp
.Release_And_Save
(M
, Result
);
1582 function UI_From_CC
(Input
: Char_Code
) return Uint
is
1584 return UI_From_Dint
(Dint
(Input
));
1591 function UI_From_Dint
(Input
: Dint
) return Uint
is
1594 if Dint
(Min_Direct
) <= Input
and then Input
<= Dint
(Max_Direct
) then
1595 return Uint
(Dint
(Uint_Direct_Bias
) + Input
);
1597 -- For values of larger magnitude, compute digits into a vector and
1598 -- call Vector_To_Uint.
1602 Max_For_Dint
: constant := 5;
1603 -- Base is defined so that 5 Uint digits is sufficient
1604 -- to hold the largest possible Dint value.
1606 V
: UI_Vector
(1 .. Max_For_Dint
);
1608 Temp_Integer
: Dint
;
1611 for J
in V
'Range loop
1615 Temp_Integer
:= Input
;
1617 for J
in reverse V
'Range loop
1618 V
(J
) := Int
(abs (Temp_Integer
rem Dint
(Base
)));
1619 Temp_Integer
:= Temp_Integer
/ Dint
(Base
);
1622 return Vector_To_Uint
(V
, Input
< Dint
'(0));
1631 function UI_From_Int (Input : Int) return Uint is
1635 if Min_Direct <= Input and then Input <= Max_Direct then
1636 return Uint (Int (Uint_Direct_Bias) + Input);
1639 -- If already in the hash table, return entry
1641 U := UI_Ints.Get (Input);
1643 if U /= No_Uint then
1647 -- For values of larger magnitude, compute digits into a vector and
1648 -- call Vector_To_Uint.
1651 Max_For_Int : constant := 3;
1652 -- Base is defined so that 3 Uint digits is sufficient
1653 -- to hold the largest possible Int value.
1655 V : UI_Vector (1 .. Max_For_Int);
1660 for J in V'Range loop
1664 Temp_Integer := Input;
1666 for J in reverse V'Range loop
1667 V (J) := abs (Temp_Integer rem Base);
1668 Temp_Integer := Temp_Integer / Base;
1671 U := Vector_To_Uint (V, Input < Int_0);
1672 UI_Ints.Set (Input, U);
1673 Uints_Min := Uints.Last;
1674 Udigits_Min := Udigits.Last;
1683 -- Lehmer's algorithm for GCD
1685 -- The idea is to avoid using multiple precision arithmetic wherever
1686 -- possible, substituting Int arithmetic instead. See Knuth volume II,
1687 -- Algorithm L (page 329).
1689 -- We use the same notation as Knuth (U_Hat standing for the obvious!)
1691 function UI_GCD (Uin, Vin : Uint) return Uint is
1693 -- Copies of Uin and Vin
1696 -- The most Significant digits of U,V
1698 A, B, C, D, T, Q, Den1, Den2 : Int;
1701 Marks : constant Uintp.Save_Mark := Uintp.Mark;
1702 Iterations : Integer := 0;
1705 pragma Assert (Uin >= Vin);
1706 pragma Assert (Vin >= Uint_0);
1712 Iterations := Iterations + 1;
1719 UI_From_Int (GCD (Direct_Val (V), UI_To_Int (U rem V)));
1723 Most_Sig_2_Digits (U, V, U_Hat, V_Hat);
1730 -- We might overflow and get division by zero here. This just
1731 -- means we cannot take the single precision step
1735 exit when (Den1 * Den2) = Int_0;
1737 -- Compute Q, the trial quotient
1739 Q := (U_Hat + A) / Den1;
1741 exit when Q /= ((U_Hat + B) / Den2);
1743 -- A single precision step Euclid step will give same answer as
1744 -- a multiprecision one.
1754 T := U_Hat - (Q * V_Hat);
1760 -- Take a multiprecision Euclid step
1764 -- No single precision steps take a regular Euclid step
1771 -- Use prior single precision steps to compute this Euclid step
1773 -- Fixed bug 1415-008 spends 80% of its time working on this
1774 -- step. Perhaps we need a special case Int / Uint dot
1775 -- product to speed things up. ???
1777 -- Alternatively we could increase the single precision
1778 -- iterations to handle Uint's of some small size ( <5
1779 -- digits?). Then we would have more iterations on small Uint.
1780 -- Fixed bug 1415-008 only gets 5 (on average) single
1781 -- precision iterations per large iteration. ???
1783 Tmp_UI := (UI_From_Int (A) * U) + (UI_From_Int (B) * V);
1784 V := (UI_From_Int (C) * U) + (UI_From_Int (D) * V);
1788 -- If the operands are very different in magnitude, the loop
1789 -- will generate large amounts of short-lived data, which it is
1790 -- worth removing periodically.
1792 if Iterations > 100 then
1793 Release_And_Save (Marks, U, V);
1803 function UI_Ge (Left : Int; Right : Uint) return Boolean is
1805 return not UI_Lt (UI_From_Int (Left), Right);
1808 function UI_Ge (Left : Uint; Right : Int) return Boolean is
1810 return not UI_Lt (Left, UI_From_Int (Right));
1813 function UI_Ge (Left : Uint; Right : Uint) return Boolean is
1815 return not UI_Lt (Left, Right);
1822 function UI_Gt (Left : Int; Right : Uint) return Boolean is
1824 return UI_Lt (Right, UI_From_Int (Left));
1827 function UI_Gt (Left : Uint; Right : Int) return Boolean is
1829 return UI_Lt (UI_From_Int (Right), Left);
1832 function UI_Gt (Left : Uint; Right : Uint) return Boolean is
1834 return UI_Lt (Right, Left);
1841 procedure UI_Image (Input : Uint; Format : UI_Format := Auto) is
1843 Image_Out (Input, True, Format);
1846 -------------------------
1847 -- UI_Is_In_Int_Range --
1848 -------------------------
1850 function UI_Is_In_Int_Range (Input : Uint) return Boolean is
1852 -- Make sure we don't get called before Initialize
1854 pragma Assert (Uint_Int_First /= Uint_0);
1856 if Direct (Input) then
1859 return Input >= Uint_Int_First
1860 and then Input <= Uint_Int_Last;
1862 end UI_Is_In_Int_Range;
1868 function UI_Le (Left : Int; Right : Uint) return Boolean is
1870 return not UI_Lt (Right, UI_From_Int (Left));
1873 function UI_Le (Left : Uint; Right : Int) return Boolean is
1875 return not UI_Lt (UI_From_Int (Right), Left);
1878 function UI_Le (Left : Uint; Right : Uint) return Boolean is
1880 return not UI_Lt (Right, Left);
1887 function UI_Lt (Left : Int; Right : Uint) return Boolean is
1889 return UI_Lt (UI_From_Int (Left), Right);
1892 function UI_Lt (Left : Uint; Right : Int) return Boolean is
1894 return UI_Lt (Left, UI_From_Int (Right));
1897 function UI_Lt (Left : Uint; Right : Uint) return Boolean is
1899 -- Quick processing for identical arguments
1901 if Int (Left) = Int (Right) then
1904 -- Quick processing for both arguments directly represented
1906 elsif Direct (Left) and then Direct (Right) then
1907 return Int (Left) < Int (Right);
1909 -- At least one argument is more than one digit long
1913 L_Length : constant Int := N_Digits (Left);
1914 R_Length : constant Int := N_Digits (Right);
1916 L_Vec : UI_Vector (1 .. L_Length);
1917 R_Vec : UI_Vector (1 .. R_Length);
1920 Init_Operand (Left, L_Vec);
1921 Init_Operand (Right, R_Vec);
1923 if L_Vec (1) < Int_0 then
1925 -- First argument negative, second argument non-negative
1927 if R_Vec (1) >= Int_0 then
1930 -- Both arguments negative
1933 if L_Length /= R_Length then
1934 return L_Length > R_Length;
1936 elsif L_Vec (1) /= R_Vec (1) then
1937 return L_Vec (1) < R_Vec (1);
1940 for J in 2 .. L_Vec'Last loop
1941 if L_Vec (J) /= R_Vec (J) then
1942 return L_Vec (J) > R_Vec (J);
1951 -- First argument non-negative, second argument negative
1953 if R_Vec (1) < Int_0 then
1956 -- Both arguments non-negative
1959 if L_Length /= R_Length then
1960 return L_Length < R_Length;
1962 for J in L_Vec'Range loop
1963 if L_Vec (J) /= R_Vec (J) then
1964 return L_Vec (J) < R_Vec (J);
1980 function UI_Max (Left : Int; Right : Uint) return Uint is
1982 return UI_Max (UI_From_Int (Left), Right);
1985 function UI_Max (Left : Uint; Right : Int) return Uint is
1987 return UI_Max (Left, UI_From_Int (Right));
1990 function UI_Max (Left : Uint; Right : Uint) return Uint is
1992 if Left >= Right then
2003 function UI_Min (Left : Int; Right : Uint) return Uint is
2005 return UI_Min (UI_From_Int (Left), Right);
2008 function UI_Min (Left : Uint; Right : Int) return Uint is
2010 return UI_Min (Left, UI_From_Int (Right));
2013 function UI_Min (Left : Uint; Right : Uint) return Uint is
2015 if Left <= Right then
2026 function UI_Mod (Left : Int; Right : Uint) return Uint is
2028 return UI_Mod (UI_From_Int (Left), Right);
2031 function UI_Mod (Left : Uint; Right : Int) return Uint is
2033 return UI_Mod (Left, UI_From_Int (Right));
2036 function UI_Mod (Left : Uint; Right : Uint) return Uint is
2037 Urem : constant Uint := Left rem Right;
2040 if (Left < Uint_0) = (Right < Uint_0)
2041 or else Urem = Uint_0
2045 return Right + Urem;
2053 function UI_Mul (Left : Int; Right : Uint) return Uint is
2055 return UI_Mul (UI_From_Int (Left), Right);
2058 function UI_Mul (Left : Uint; Right : Int) return Uint is
2060 return UI_Mul (Left, UI_From_Int (Right));
2063 function UI_Mul (Left : Uint; Right : Uint) return Uint is
2065 -- Simple case of single length operands
2067 if Direct (Left) and then Direct (Right) then
2070 (Dint (Direct_Val (Left)) * Dint (Direct_Val (Right)));
2073 -- Otherwise we have the general case (Algorithm M in Knuth)
2076 L_Length : constant Int := N_Digits (Left);
2077 R_Length : constant Int := N_Digits (Right);
2078 L_Vec : UI_Vector (1 .. L_Length);
2079 R_Vec : UI_Vector (1 .. R_Length);
2083 Init_Operand (Left, L_Vec);
2084 Init_Operand (Right, R_Vec);
2085 Neg := (L_Vec (1) < Int_0) xor (R_Vec (1) < Int_0);
2086 L_Vec (1) := abs (L_Vec (1));
2087 R_Vec (1) := abs (R_Vec (1));
2089 Algorithm_M : declare
2090 Product : UI_Vector (1 .. L_Length + R_Length);
2095 for J in Product'Range loop
2099 for J in reverse R_Vec'Range loop
2101 for K in reverse L_Vec'Range loop
2103 L_Vec (K) * R_Vec (J) + Product (J + K) + Carry;
2104 Product (J + K) := Tmp_Sum rem Base;
2105 Carry := Tmp_Sum / Base;
2108 Product (J) := Carry;
2111 return Vector_To_Uint (Product, Neg);
2120 function UI_Ne (Left : Int; Right : Uint) return Boolean is
2122 return UI_Ne (UI_From_Int (Left), Right);
2125 function UI_Ne (Left : Uint; Right : Int) return Boolean is
2127 return UI_Ne (Left, UI_From_Int (Right));
2130 function UI_Ne (Left : Uint; Right : Uint) return Boolean is
2132 -- Quick processing for identical arguments. Note that this takes
2133 -- care of the case of two No_Uint arguments.
2135 if Int (Left) = Int (Right) then
2139 -- See if left operand directly represented
2141 if Direct (Left) then
2143 -- If right operand directly represented then compare
2145 if Direct (Right) then
2146 return Int (Left) /= Int (Right);
2148 -- Left operand directly represented, right not, must be unequal
2154 -- Right operand directly represented, left not, must be unequal
2156 elsif Direct (Right) then
2160 -- Otherwise both multi-word, do comparison
2163 Size : constant Int := N_Digits (Left);
2168 if Size /= N_Digits (Right) then
2172 Left_Loc := Uints.Table (Left).Loc;
2173 Right_Loc := Uints.Table (Right).Loc;
2175 for J in Int_0 .. Size - Int_1 loop
2176 if Udigits.Table (Left_Loc + J) /=
2177 Udigits.Table (Right_Loc + J)
2191 function UI_Negate (Right : Uint) return Uint is
2193 -- Case where input is directly represented. Note that since the
2194 -- range of Direct values is non-symmetrical, the result may not
2195 -- be directly represented, this is taken care of in UI_From_Int.
2197 if Direct (Right) then
2198 return UI_From_Int (-Direct_Val (Right));
2200 -- Full processing for multi-digit case. Note that we cannot just
2201 -- copy the value to the end of the table negating the first digit,
2202 -- since the range of Direct values is non-symmetrical, so we can
2203 -- have a negative value that is not Direct whose negation can be
2204 -- represented directly.
2208 R_Length : constant Int := N_Digits (Right);
2209 R_Vec : UI_Vector (1 .. R_Length);
2213 Init_Operand (Right, R_Vec);
2214 Neg := R_Vec (1) > Int_0;
2215 R_Vec (1) := abs R_Vec (1);
2216 return Vector_To_Uint (R_Vec, Neg);
2225 function UI_Rem (Left : Int; Right : Uint) return Uint is
2227 return UI_Rem (UI_From_Int (Left), Right);
2230 function UI_Rem (Left : Uint; Right : Int) return Uint is
2232 return UI_Rem (Left, UI_From_Int (Right));
2235 function UI_Rem (Left, Right : Uint) return Uint is
2239 subtype Int1_12 is Integer range 1 .. 12;
2242 pragma Assert (Right /= Uint_0);
2244 if Direct (Right) then
2245 if Direct (Left) then
2246 return UI_From_Int (Direct_Val (Left) rem Direct_Val (Right));
2249 -- Special cases when Right is less than 13 and Left is larger
2250 -- larger than one digit. All of these algorithms depend on the
2251 -- base being 2 ** 15 We work with Abs (Left) and Abs(Right)
2252 -- then multiply result by Sign (Left)
2254 if (Right <= Uint_12) and then (Right >= Uint_Minus_12) then
2256 if Left < Uint_0 then
2262 -- All cases are listed, grouped by mathematical method
2263 -- It is not inefficient to do have this case list out
2264 -- of order since GCC sorts the cases we list.
2266 case Int1_12 (abs (Direct_Val (Right))) is
2271 -- Powers of two are simple AND's with LS Left Digit
2272 -- GCC will recognise these constants as powers of 2
2273 -- and replace the rem with simpler operations where
2276 -- Least_Sig_Digit might return Negative numbers
2279 return UI_From_Int (
2280 Sign * (Least_Sig_Digit (Left) mod 2));
2283 return UI_From_Int (
2284 Sign * (Least_Sig_Digit (Left) mod 4));
2287 return UI_From_Int (
2288 Sign * (Least_Sig_Digit (Left) mod 8));
2290 -- Some number theoretical tricks:
2292 -- If B Rem Right = 1 then
2293 -- Left Rem Right = Sum_Of_Digits_Base_B (Left) Rem Right
2295 -- Note: 2^32 mod 3 = 1
2298 return UI_From_Int (
2299 Sign * (Sum_Double_Digits (Left, 1) rem Int (3)));
2301 -- Note: 2^15 mod 7 = 1
2304 return UI_From_Int (
2305 Sign * (Sum_Digits (Left, 1) rem Int (7)));
2307 -- Note: 2^32 mod 5 = -1
2308 -- Alternating sums might be negative, but rem is always
2309 -- positive hence we must use mod here.
2312 Tmp := Sum_Double_Digits (Left, -1) mod Int (5);
2313 return UI_From_Int (Sign * Tmp);
2315 -- Note: 2^15 mod 9 = -1
2316 -- Alternating sums might be negative, but rem is always
2317 -- positive hence we must use mod here.
2320 Tmp := Sum_Digits (Left, -1) mod Int (9);
2321 return UI_From_Int (Sign * Tmp);
2323 -- Note: 2^15 mod 11 = -1
2324 -- Alternating sums might be negative, but rem is always
2325 -- positive hence we must use mod here.
2328 Tmp := Sum_Digits (Left, -1) mod Int (11);
2329 return UI_From_Int (Sign * Tmp);
2331 -- Now resort to Chinese Remainder theorem
2332 -- to reduce 6, 10, 12 to previous special cases
2334 -- There is no reason we could not add more cases
2335 -- like these if it proves useful.
2337 -- Perhaps we should go up to 16, however
2338 -- I have no "trick" for 13.
2340 -- To find u mod m we:
2342 -- GCD(m1, m2) = 1 AND m = (m1 * m2).
2343 -- Next we pick (Basis) M1, M2 small S.T.
2344 -- (M1 mod m1) = (M2 mod m2) = 1 AND
2345 -- (M1 mod m2) = (M2 mod m1) = 0
2347 -- So u mod m = (u1 * M1 + u2 * M2) mod m
2348 -- Where u1 = (u mod m1) AND u2 = (u mod m2);
2349 -- Under typical circumstances the last mod m
2350 -- can be done with a (possible) single subtraction.
2352 -- m1 = 2; m2 = 3; M1 = 3; M2 = 4;
2355 Tmp := 3 * (Least_Sig_Digit (Left) rem 2) +
2356 4 * (Sum_Double_Digits (Left, 1) rem 3);
2357 return UI_From_Int (Sign * (Tmp rem 6));
2359 -- m1 = 2; m2 = 5; M1 = 5; M2 = 6;
2362 Tmp := 5 * (Least_Sig_Digit (Left) rem 2) +
2363 6 * (Sum_Double_Digits (Left, -1) mod 5);
2364 return UI_From_Int (Sign * (Tmp rem 10));
2366 -- m1 = 3; m2 = 4; M1 = 4; M2 = 9;
2369 Tmp := 4 * (Sum_Double_Digits (Left, 1) rem 3) +
2370 9 * (Least_Sig_Digit (Left) rem 4);
2371 return UI_From_Int (Sign * (Tmp rem 12));
2376 -- Else fall through to general case
2378 -- ???This needs to be improved. We have the Rem when we do the
2379 -- Div. Div throws it away!
2381 -- The special case Length (Left) = Length(right) = 1 in Div
2382 -- looks slow. It uses UI_To_Int when Int should suffice. ???
2386 return Left - (Left / Right) * Right;
2393 function UI_Sub (Left : Int; Right : Uint) return Uint is
2395 return UI_Add (Left, -Right);
2398 function UI_Sub (Left : Uint; Right : Int) return Uint is
2400 return UI_Add (Left, -Right);
2403 function UI_Sub (Left : Uint; Right : Uint) return Uint is
2405 if Direct (Left) and then Direct (Right) then
2406 return UI_From_Int (Direct_Val (Left) - Direct_Val (Right));
2408 return UI_Add (Left, -Right);
2416 function UI_To_CC (Input : Uint) return Char_Code is
2418 if Direct (Input) then
2419 return Char_Code (Direct_Val (Input));
2421 -- Case of input is more than one digit
2425 In_Length : constant Int := N_Digits (Input);
2426 In_Vec : UI_Vector (1 .. In_Length);
2430 Init_Operand (Input, In_Vec);
2432 -- We assume value is positive
2435 for Idx in In_Vec'Range loop
2436 Ret_CC := Ret_CC * Char_Code (Base) +
2437 Char_Code (abs In_Vec (Idx));
2449 function UI_To_Int (Input : Uint) return Int is
2451 if Direct (Input) then
2452 return Direct_Val (Input);
2454 -- Case of input is more than one digit
2458 In_Length : constant Int := N_Digits (Input);
2459 In_Vec : UI_Vector (1 .. In_Length);
2463 -- Uints of more than one digit could be outside the range for
2464 -- Ints. Caller should have checked for this if not certain.
2465 -- Fatal error to attempt to convert from value outside Int'Range.
2467 pragma Assert (UI_Is_In_Int_Range (Input));
2469 -- Otherwise, proceed ahead, we are OK
2471 Init_Operand (Input, In_Vec);
2474 -- Calculate -|Input| and then negates if value is positive.
2475 -- This handles our current definition of Int (based on
2476 -- 2s complement). Is it secure enough?
2478 for Idx in In_Vec'Range loop
2479 Ret_Int := Ret_Int * Base - abs In_Vec (Idx);
2482 if In_Vec (1) < Int_0 then
2495 procedure UI_Write (Input : Uint; Format : UI_Format := Auto) is
2497 Image_Out (Input, False, Format);
2500 ---------------------
2501 -- Vector_To_Uint --
2502 ---------------------
2504 function Vector_To_Uint
2505 (In_Vec : UI_Vector;
2513 -- The vector can contain leading zeros. These are not stored in the
2514 -- table, so loop through the vector looking for first non-zero digit
2516 for J in In_Vec'Range loop
2517 if In_Vec (J) /= Int_0 then
2519 -- The length of the value is the length of the rest of the vector
2521 Size := In_Vec'Last - J + 1;
2523 -- One digit value can always be represented directly
2525 if Size = Int_1 then
2527 return Uint (Int (Uint_Direct_Bias) - In_Vec (J));
2529 return Uint (Int (Uint_Direct_Bias) + In_Vec (J));
2532 -- Positive two digit values may be in direct representation range
2534 elsif Size = Int_2 and then not Negative then
2535 Val := In_Vec (J) * Base + In_Vec (J + 1);
2537 if Val <= Max_Direct then
2538 return Uint (Int (Uint_Direct_Bias) + Val);
2542 -- The value is outside the direct representation range and
2543 -- must therefore be stored in the table. Expand the table
2544 -- to contain the count and tigis. The index of the new table
2545 -- entry will be returned as the result.
2547 Uints.Increment_Last;
2548 Uints.Table (Uints.Last).Length := Size;
2549 Uints.Table (Uints.Last).Loc := Udigits.Last + 1;
2551 Udigits.Increment_Last;
2554 Udigits.Table (Udigits.Last) := -In_Vec (J);
2556 Udigits.Table (Udigits.Last) := +In_Vec (J);
2559 for K in 2 .. Size loop
2560 Udigits.Increment_Last;
2561 Udigits.Table (Udigits.Last) := In_Vec (J + K - 1);
2568 -- Dropped through loop only if vector contained all zeros