1------------------------------------------------------------------------------
2--                                                                          --
3--                         GNAT COMPILER COMPONENTS                         --
4--                                                                          --
5--                                U I N T P                                 --
6--                                                                          --
7--                                 B o d y                                  --
8--                                                                          --
9--          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
10--                                                                          --
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.                                     --
17--                                                                          --
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.               --
21--                                                                          --
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/>.                                          --
26--                                                                          --
27-- GNAT was originally developed  by the GNAT team at  New York University. --
28-- Extensive contributions were provided by Ada Core Technologies Inc.      --
29--                                                                          --
30------------------------------------------------------------------------------
31
32with Output;  use Output;
33with Tree_IO; use Tree_IO;
34
35with GNAT.HTable; use GNAT.HTable;
36
37package body Uintp is
38
39   ------------------------
40   -- Local Declarations --
41   ------------------------
42
43   Uint_Int_First : Uint := Uint_0;
44   --  Uint value containing Int'First value, set by Initialize. The initial
45   --  value of Uint_0 is used for an assertion check that ensures that this
46   --  value is not used before it is initialized. This value is used in the
47   --  UI_Is_In_Int_Range predicate, and it is right that this is a host value,
48   --  since the issue is host representation of integer values.
49
50   Uint_Int_Last : Uint;
51   --  Uint value containing Int'Last value set by Initialize
52
53   UI_Power_2 : array (Int range 0 .. 64) of Uint;
54   --  This table is used to memoize exponentiations by powers of 2. The Nth
55   --  entry, if set, contains the Uint value 2 ** N. Initially UI_Power_2_Set
56   --  is zero and only the 0'th entry is set, the invariant being that all
57   --  entries in the range 0 .. UI_Power_2_Set are initialized.
58
59   UI_Power_2_Set : Nat;
60   --  Number of entries set in UI_Power_2;
61
62   UI_Power_10 : array (Int range 0 .. 64) of Uint;
63   --  This table is used to memoize exponentiations by powers of 10 in the
64   --  same manner as described above for UI_Power_2.
65
66   UI_Power_10_Set : Nat;
67   --  Number of entries set in UI_Power_10;
68
69   Uints_Min   : Uint;
70   Udigits_Min : Int;
71   --  These values are used to make sure that the mark/release mechanism does
72   --  not destroy values saved in the U_Power tables or in the hash table used
73   --  by UI_From_Int. Whenever an entry is made in either of these tables,
74   --  Uints_Min and Udigits_Min are updated to protect the entry, and Release
75   --  never cuts back beyond these minimum values.
76
77   Int_0 : constant Int := 0;
78   Int_1 : constant Int := 1;
79   Int_2 : constant Int := 2;
80   --  These values are used in some cases where the use of numeric literals
81   --  would cause ambiguities (integer vs Uint).
82
83   ----------------------------
84   -- UI_From_Int Hash Table --
85   ----------------------------
86
87   --  UI_From_Int uses a hash table to avoid duplicating entries and wasting
88   --  storage. This is particularly important for complex cases of back
89   --  annotation.
90
91   subtype Hnum is Nat range 0 .. 1022;
92
93   function Hash_Num (F : Int) return Hnum;
94   --  Hashing function
95
96   package UI_Ints is new Simple_HTable (
97     Header_Num => Hnum,
98     Element    => Uint,
99     No_Element => No_Uint,
100     Key        => Int,
101     Hash       => Hash_Num,
102     Equal      => "=");
103
104   -----------------------
105   -- Local Subprograms --
106   -----------------------
107
108   function Direct (U : Uint) return Boolean;
109   pragma Inline (Direct);
110   --  Returns True if U is represented directly
111
112   function Direct_Val (U : Uint) return Int;
113   --  U is a Uint for is represented directly. The returned result is the
114   --  value represented.
115
116   function GCD (Jin, Kin : Int) return Int;
117   --  Compute GCD of two integers. Assumes that Jin >= Kin >= 0
118
119   procedure Image_Out
120     (Input     : Uint;
121      To_Buffer : Boolean;
122      Format    : UI_Format);
123   --  Common processing for UI_Image and UI_Write, To_Buffer is set True for
124   --  UI_Image, and false for UI_Write, and Format is copied from the Format
125   --  parameter to UI_Image or UI_Write.
126
127   procedure Init_Operand (UI : Uint; Vec : out UI_Vector);
128   pragma Inline (Init_Operand);
129   --  This procedure puts the value of UI into the vector in canonical
130   --  multiple precision format. The parameter should be of the correct size
131   --  as determined by a previous call to N_Digits (UI). The first digit of
132   --  Vec contains the sign, all other digits are always non-negative. Note
133   --  that the input may be directly represented, and in this case Vec will
134   --  contain the corresponding one or two digit value. The low bound of Vec
135   --  is always 1.
136
137   function Least_Sig_Digit (Arg : Uint) return Int;
138   pragma Inline (Least_Sig_Digit);
139   --  Returns the Least Significant Digit of Arg quickly. When the given Uint
140   --  is less than 2**15, the value returned is the input value, in this case
141   --  the result may be negative. It is expected that any use will mask off
142   --  unnecessary bits. This is used for finding Arg mod B where B is a power
143   --  of two. Hence the actual base is irrelevant as long as it is a power of
144   --  two.
145
146   procedure Most_Sig_2_Digits
147     (Left      : Uint;
148      Right     : Uint;
149      Left_Hat  : out Int;
150      Right_Hat : out Int);
151   --  Returns leading two significant digits from the given pair of Uint's.
152   --  Mathematically: returns Left / (Base ** K) and Right / (Base ** K) where
153   --  K is as small as possible S.T. Right_Hat < Base * Base. It is required
154   --  that Left > Right for the algorithm to work.
155
156   function N_Digits (Input : Uint) return Int;
157   pragma Inline (N_Digits);
158   --  Returns number of "digits" in a Uint
159
160   procedure UI_Div_Rem
161     (Left, Right       : Uint;
162      Quotient          : out Uint;
163      Remainder         : out Uint;
164      Discard_Quotient  : Boolean := False;
165      Discard_Remainder : Boolean := False);
166   --  Compute Euclidean division of Left by Right. If Discard_Quotient is
167   --  False then the quotient is returned in Quotient (otherwise Quotient is
168   --  set to No_Uint). If Discard_Remainder is False, then the remainder is
169   --  returned in Remainder (otherwise Remainder is set to No_Uint).
170   --
171   --  If Discard_Quotient is True, Quotient is set to No_Uint
172   --  If Discard_Remainder is True, Remainder is set to No_Uint
173
174   function Vector_To_Uint
175     (In_Vec   : UI_Vector;
176      Negative : Boolean) return Uint;
177   --  Functions that calculate values in UI_Vectors, call this function to
178   --  create and return the Uint value. In_Vec contains the multiple precision
179   --  (Base) representation of a non-negative value. Leading zeroes are
180   --  permitted. Negative is set if the desired result is the negative of the
181   --  given value. The result will be either the appropriate directly
182   --  represented value, or a table entry in the proper canonical format is
183   --  created and returned.
184   --
185   --  Note that Init_Operand puts a signed value in the result vector, but
186   --  Vector_To_Uint is always presented with a non-negative value. The
187   --  processing of signs is something that is done by the caller before
188   --  calling Vector_To_Uint.
189
190   ------------
191   -- Direct --
192   ------------
193
194   function Direct (U : Uint) return Boolean is
195   begin
196      return Int (U) <= Int (Uint_Direct_Last);
197   end Direct;
198
199   ----------------
200   -- Direct_Val --
201   ----------------
202
203   function Direct_Val (U : Uint) return Int is
204   begin
205      pragma Assert (Direct (U));
206      return Int (U) - Int (Uint_Direct_Bias);
207   end Direct_Val;
208
209   ---------
210   -- GCD --
211   ---------
212
213   function GCD (Jin, Kin : Int) return Int is
214      J, K, Tmp : Int;
215
216   begin
217      pragma Assert (Jin >= Kin);
218      pragma Assert (Kin >= Int_0);
219
220      J := Jin;
221      K := Kin;
222      while K /= Uint_0 loop
223         Tmp := J mod K;
224         J := K;
225         K := Tmp;
226      end loop;
227
228      return J;
229   end GCD;
230
231   --------------
232   -- Hash_Num --
233   --------------
234
235   function Hash_Num (F : Int) return Hnum is
236   begin
237      return Types."mod" (F, Hnum'Range_Length);
238   end Hash_Num;
239
240   ---------------
241   -- Image_Out --
242   ---------------
243
244   procedure Image_Out
245     (Input     : Uint;
246      To_Buffer : Boolean;
247      Format    : UI_Format)
248   is
249      Marks  : constant Uintp.Save_Mark := Uintp.Mark;
250      Base   : Uint;
251      Ainput : Uint;
252
253      Digs_Output : Natural := 0;
254      --  Counts digits output. In hex mode, but not in decimal mode, we
255      --  put an underline after every four hex digits that are output.
256
257      Exponent : Natural := 0;
258      --  If the number is too long to fit in the buffer, we switch to an
259      --  approximate output format with an exponent. This variable records
260      --  the exponent value.
261
262      function Better_In_Hex return Boolean;
263      --  Determines if it is better to generate digits in base 16 (result
264      --  is true) or base 10 (result is false). The choice is purely a
265      --  matter of convenience and aesthetics, so it does not matter which
266      --  value is returned from a correctness point of view.
267
268      procedure Image_Char (C : Character);
269      --  Internal procedure to output one character
270
271      procedure Image_Exponent (N : Natural);
272      --  Output non-zero exponent. Note that we only use the exponent form in
273      --  the buffer case, so we know that To_Buffer is true.
274
275      procedure Image_Uint (U : Uint);
276      --  Internal procedure to output characters of non-negative Uint
277
278      -------------------
279      -- Better_In_Hex --
280      -------------------
281
282      function Better_In_Hex return Boolean is
283         T16 : constant Uint := Uint_2 ** Int'(16);
284         A   : Uint;
285
286      begin
287         A := UI_Abs (Input);
288
289         --  Small values up to 2**16 can always be in decimal
290
291         if A < T16 then
292            return False;
293         end if;
294
295         --  Otherwise, see if we are a power of 2 or one less than a power
296         --  of 2. For the moment these are the only cases printed in hex.
297
298         if A mod Uint_2 = Uint_1 then
299            A := A + Uint_1;
300         end if;
301
302         loop
303            if A mod T16 /= Uint_0 then
304               return False;
305
306            else
307               A := A / T16;
308            end if;
309
310            exit when A < T16;
311         end loop;
312
313         while A > Uint_2 loop
314            if A mod Uint_2 /= Uint_0 then
315               return False;
316
317            else
318               A := A / Uint_2;
319            end if;
320         end loop;
321
322         return True;
323      end Better_In_Hex;
324
325      ----------------
326      -- Image_Char --
327      ----------------
328
329      procedure Image_Char (C : Character) is
330      begin
331         if To_Buffer then
332            if UI_Image_Length + 6 > UI_Image_Max then
333               Exponent := Exponent + 1;
334            else
335               UI_Image_Length := UI_Image_Length + 1;
336               UI_Image_Buffer (UI_Image_Length) := C;
337            end if;
338         else
339            Write_Char (C);
340         end if;
341      end Image_Char;
342
343      --------------------
344      -- Image_Exponent --
345      --------------------
346
347      procedure Image_Exponent (N : Natural) is
348      begin
349         if N >= 10 then
350            Image_Exponent (N / 10);
351         end if;
352
353         UI_Image_Length := UI_Image_Length + 1;
354         UI_Image_Buffer (UI_Image_Length) :=
355           Character'Val (Character'Pos ('0') + N mod 10);
356      end Image_Exponent;
357
358      ----------------
359      -- Image_Uint --
360      ----------------
361
362      procedure Image_Uint (U : Uint) is
363         H : constant array (Int range 0 .. 15) of Character :=
364               "0123456789ABCDEF";
365
366         Q, R : Uint;
367      begin
368         UI_Div_Rem (U, Base, Q, R);
369
370         if Q > Uint_0 then
371            Image_Uint (Q);
372         end if;
373
374         if Digs_Output = 4 and then Base = Uint_16 then
375            Image_Char ('_');
376            Digs_Output := 0;
377         end if;
378
379         Image_Char (H (UI_To_Int (R)));
380
381         Digs_Output := Digs_Output + 1;
382      end Image_Uint;
383
384   --  Start of processing for Image_Out
385
386   begin
387      if Input = No_Uint then
388         Image_Char ('?');
389         return;
390      end if;
391
392      UI_Image_Length := 0;
393
394      if Input < Uint_0 then
395         Image_Char ('-');
396         Ainput := -Input;
397      else
398         Ainput := Input;
399      end if;
400
401      if Format = Hex
402        or else (Format = Auto and then Better_In_Hex)
403      then
404         Base := Uint_16;
405         Image_Char ('1');
406         Image_Char ('6');
407         Image_Char ('#');
408         Image_Uint (Ainput);
409         Image_Char ('#');
410
411      else
412         Base := Uint_10;
413         Image_Uint (Ainput);
414      end if;
415
416      if Exponent /= 0 then
417         UI_Image_Length := UI_Image_Length + 1;
418         UI_Image_Buffer (UI_Image_Length) := 'E';
419         Image_Exponent (Exponent);
420      end if;
421
422      Uintp.Release (Marks);
423   end Image_Out;
424
425   -------------------
426   -- Init_Operand --
427   -------------------
428
429   procedure Init_Operand (UI : Uint; Vec : out UI_Vector) is
430      Loc : Int;
431
432      pragma Assert (Vec'First = Int'(1));
433
434   begin
435      if Direct (UI) then
436         Vec (1) := Direct_Val (UI);
437
438         if Vec (1) >= Base then
439            Vec (2) := Vec (1) rem Base;
440            Vec (1) := Vec (1) / Base;
441         end if;
442
443      else
444         Loc := Uints.Table (UI).Loc;
445
446         for J in 1 .. Uints.Table (UI).Length loop
447            Vec (J) := Udigits.Table (Loc + J - 1);
448         end loop;
449      end if;
450   end Init_Operand;
451
452   ----------------
453   -- Initialize --
454   ----------------
455
456   procedure Initialize is
457   begin
458      Uints.Init;
459      Udigits.Init;
460
461      Uint_Int_First := UI_From_Int (Int'First);
462      Uint_Int_Last  := UI_From_Int (Int'Last);
463
464      UI_Power_2 (0) := Uint_1;
465      UI_Power_2_Set := 0;
466
467      UI_Power_10 (0) := Uint_1;
468      UI_Power_10_Set := 0;
469
470      Uints_Min := Uints.Last;
471      Udigits_Min := Udigits.Last;
472
473      UI_Ints.Reset;
474   end Initialize;
475
476   ---------------------
477   -- Least_Sig_Digit --
478   ---------------------
479
480   function Least_Sig_Digit (Arg : Uint) return Int is
481      V : Int;
482
483   begin
484      if Direct (Arg) then
485         V := Direct_Val (Arg);
486
487         if V >= Base then
488            V := V mod Base;
489         end if;
490
491         --  Note that this result may be negative
492
493         return V;
494
495      else
496         return
497           Udigits.Table
498            (Uints.Table (Arg).Loc + Uints.Table (Arg).Length - 1);
499      end if;
500   end Least_Sig_Digit;
501
502   ----------
503   -- Mark --
504   ----------
505
506   function Mark return Save_Mark is
507   begin
508      return (Save_Uint => Uints.Last, Save_Udigit => Udigits.Last);
509   end Mark;
510
511   -----------------------
512   -- Most_Sig_2_Digits --
513   -----------------------
514
515   procedure Most_Sig_2_Digits
516     (Left      : Uint;
517      Right     : Uint;
518      Left_Hat  : out Int;
519      Right_Hat : out Int)
520   is
521   begin
522      pragma Assert (Left >= Right);
523
524      if Direct (Left) then
525         Left_Hat  := Direct_Val (Left);
526         Right_Hat := Direct_Val (Right);
527         return;
528
529      else
530         declare
531            L1 : constant Int :=
532                   Udigits.Table (Uints.Table (Left).Loc);
533            L2 : constant Int :=
534                   Udigits.Table (Uints.Table (Left).Loc + 1);
535
536         begin
537            --  It is not so clear what to return when Arg is negative???
538
539            Left_Hat := abs (L1) * Base + L2;
540         end;
541      end if;
542
543      declare
544         Length_L : constant Int := Uints.Table (Left).Length;
545         Length_R : Int;
546         R1 : Int;
547         R2 : Int;
548         T  : Int;
549
550      begin
551         if Direct (Right) then
552            T := Direct_Val (Left);
553            R1 := abs (T / Base);
554            R2 := T rem Base;
555            Length_R := 2;
556
557         else
558            R1 := abs (Udigits.Table (Uints.Table (Right).Loc));
559            R2 := Udigits.Table (Uints.Table (Right).Loc + 1);
560            Length_R := Uints.Table (Right).Length;
561         end if;
562
563         if Length_L = Length_R then
564            Right_Hat := R1 * Base + R2;
565         elsif Length_L = Length_R + Int_1 then
566            Right_Hat := R1;
567         else
568            Right_Hat := 0;
569         end if;
570      end;
571   end Most_Sig_2_Digits;
572
573   ---------------
574   -- N_Digits --
575   ---------------
576
577   --  Note: N_Digits returns 1 for No_Uint
578
579   function N_Digits (Input : Uint) return Int is
580   begin
581      if Direct (Input) then
582         if Direct_Val (Input) >= Base then
583            return 2;
584         else
585            return 1;
586         end if;
587
588      else
589         return Uints.Table (Input).Length;
590      end if;
591   end N_Digits;
592
593   --------------
594   -- Num_Bits --
595   --------------
596
597   function Num_Bits (Input : Uint) return Nat is
598      Bits : Nat;
599      Num  : Nat;
600
601   begin
602      --  Largest negative number has to be handled specially, since it is in
603      --  Int_Range, but we cannot take the absolute value.
604
605      if Input = Uint_Int_First then
606         return Int'Size;
607
608      --  For any other number in Int_Range, get absolute value of number
609
610      elsif UI_Is_In_Int_Range (Input) then
611         Num := abs (UI_To_Int (Input));
612         Bits := 0;
613
614      --  If not in Int_Range then initialize bit count for all low order
615      --  words, and set number to high order digit.
616
617      else
618         Bits := Base_Bits * (Uints.Table (Input).Length - 1);
619         Num  := abs (Udigits.Table (Uints.Table (Input).Loc));
620      end if;
621
622      --  Increase bit count for remaining value in Num
623
624      while Types.">" (Num, 0) loop
625         Num := Num / 2;
626         Bits := Bits + 1;
627      end loop;
628
629      return Bits;
630   end Num_Bits;
631
632   ---------
633   -- pid --
634   ---------
635
636   procedure pid (Input : Uint) is
637   begin
638      UI_Write (Input, Decimal);
639      Write_Eol;
640   end pid;
641
642   ---------
643   -- pih --
644   ---------
645
646   procedure pih (Input : Uint) is
647   begin
648      UI_Write (Input, Hex);
649      Write_Eol;
650   end pih;
651
652   -------------
653   -- Release --
654   -------------
655
656   procedure Release (M : Save_Mark) is
657   begin
658      Uints.Set_Last   (Uint'Max (M.Save_Uint,   Uints_Min));
659      Udigits.Set_Last (Int'Max  (M.Save_Udigit, Udigits_Min));
660   end Release;
661
662   ----------------------
663   -- Release_And_Save --
664   ----------------------
665
666   procedure Release_And_Save (M : Save_Mark; UI : in out Uint) is
667   begin
668      if Direct (UI) then
669         Release (M);
670
671      else
672         declare
673            UE_Len : constant Pos := Uints.Table (UI).Length;
674            UE_Loc : constant Int := Uints.Table (UI).Loc;
675
676            UD : constant Udigits.Table_Type (1 .. UE_Len) :=
677                   Udigits.Table (UE_Loc .. UE_Loc + UE_Len - 1);
678
679         begin
680            Release (M);
681
682            Uints.Append ((Length => UE_Len, Loc => Udigits.Last + 1));
683            UI := Uints.Last;
684
685            for J in 1 .. UE_Len loop
686               Udigits.Append (UD (J));
687            end loop;
688         end;
689      end if;
690   end Release_And_Save;
691
692   procedure Release_And_Save (M : Save_Mark; UI1, UI2 : in out Uint) is
693   begin
694      if Direct (UI1) then
695         Release_And_Save (M, UI2);
696
697      elsif Direct (UI2) then
698         Release_And_Save (M, UI1);
699
700      else
701         declare
702            UE1_Len : constant Pos := Uints.Table (UI1).Length;
703            UE1_Loc : constant Int := Uints.Table (UI1).Loc;
704
705            UD1 : constant Udigits.Table_Type (1 .. UE1_Len) :=
706                    Udigits.Table (UE1_Loc .. UE1_Loc + UE1_Len - 1);
707
708            UE2_Len : constant Pos := Uints.Table (UI2).Length;
709            UE2_Loc : constant Int := Uints.Table (UI2).Loc;
710
711            UD2 : constant Udigits.Table_Type (1 .. UE2_Len) :=
712                    Udigits.Table (UE2_Loc .. UE2_Loc + UE2_Len - 1);
713
714         begin
715            Release (M);
716
717            Uints.Append ((Length => UE1_Len, Loc => Udigits.Last + 1));
718            UI1 := Uints.Last;
719
720            for J in 1 .. UE1_Len loop
721               Udigits.Append (UD1 (J));
722            end loop;
723
724            Uints.Append ((Length => UE2_Len, Loc => Udigits.Last + 1));
725            UI2 := Uints.Last;
726
727            for J in 1 .. UE2_Len loop
728               Udigits.Append (UD2 (J));
729            end loop;
730         end;
731      end if;
732   end Release_And_Save;
733
734   ---------------
735   -- Tree_Read --
736   ---------------
737
738   procedure Tree_Read is
739   begin
740      Uints.Tree_Read;
741      Udigits.Tree_Read;
742
743      Tree_Read_Int (Int (Uint_Int_First));
744      Tree_Read_Int (Int (Uint_Int_Last));
745      Tree_Read_Int (UI_Power_2_Set);
746      Tree_Read_Int (UI_Power_10_Set);
747      Tree_Read_Int (Int (Uints_Min));
748      Tree_Read_Int (Udigits_Min);
749
750      for J in 0 .. UI_Power_2_Set loop
751         Tree_Read_Int (Int (UI_Power_2 (J)));
752      end loop;
753
754      for J in 0 .. UI_Power_10_Set loop
755         Tree_Read_Int (Int (UI_Power_10 (J)));
756      end loop;
757
758   end Tree_Read;
759
760   ----------------
761   -- Tree_Write --
762   ----------------
763
764   procedure Tree_Write is
765   begin
766      Uints.Tree_Write;
767      Udigits.Tree_Write;
768
769      Tree_Write_Int (Int (Uint_Int_First));
770      Tree_Write_Int (Int (Uint_Int_Last));
771      Tree_Write_Int (UI_Power_2_Set);
772      Tree_Write_Int (UI_Power_10_Set);
773      Tree_Write_Int (Int (Uints_Min));
774      Tree_Write_Int (Udigits_Min);
775
776      for J in 0 .. UI_Power_2_Set loop
777         Tree_Write_Int (Int (UI_Power_2 (J)));
778      end loop;
779
780      for J in 0 .. UI_Power_10_Set loop
781         Tree_Write_Int (Int (UI_Power_10 (J)));
782      end loop;
783
784   end Tree_Write;
785
786   -------------
787   -- UI_Abs --
788   -------------
789
790   function UI_Abs (Right : Uint) return Uint is
791   begin
792      if Right < Uint_0 then
793         return -Right;
794      else
795         return Right;
796      end if;
797   end UI_Abs;
798
799   -------------
800   -- UI_Add --
801   -------------
802
803   function UI_Add (Left : Int; Right : Uint) return Uint is
804   begin
805      return UI_Add (UI_From_Int (Left), Right);
806   end UI_Add;
807
808   function UI_Add (Left : Uint; Right : Int) return Uint is
809   begin
810      return UI_Add (Left, UI_From_Int (Right));
811   end UI_Add;
812
813   function UI_Add (Left : Uint; Right : Uint) return Uint is
814   begin
815      --  Simple cases of direct operands and addition of zero
816
817      if Direct (Left) then
818         if Direct (Right) then
819            return UI_From_Int (Direct_Val (Left) + Direct_Val (Right));
820
821         elsif Int (Left) = Int (Uint_0) then
822            return Right;
823         end if;
824
825      elsif Direct (Right) and then Int (Right) = Int (Uint_0) then
826         return Left;
827      end if;
828
829      --  Otherwise full circuit is needed
830
831      declare
832         L_Length   : constant Int := N_Digits (Left);
833         R_Length   : constant Int := N_Digits (Right);
834         L_Vec      : UI_Vector (1 .. L_Length);
835         R_Vec      : UI_Vector (1 .. R_Length);
836         Sum_Length : Int;
837         Tmp_Int    : Int;
838         Carry      : Int;
839         Borrow     : Int;
840         X_Bigger   : Boolean := False;
841         Y_Bigger   : Boolean := False;
842         Result_Neg : Boolean := False;
843
844      begin
845         Init_Operand (Left, L_Vec);
846         Init_Operand (Right, R_Vec);
847
848         --  At least one of the two operands is in multi-digit form.
849         --  Calculate the number of digits sufficient to hold result.
850
851         if L_Length > R_Length then
852            Sum_Length := L_Length + 1;
853            X_Bigger := True;
854         else
855            Sum_Length := R_Length + 1;
856
857            if R_Length > L_Length then
858               Y_Bigger := True;
859            end if;
860         end if;
861
862         --  Make copies of the absolute values of L_Vec and R_Vec into X and Y
863         --  both with lengths equal to the maximum possibly needed. This makes
864         --  looping over the digits much simpler.
865
866         declare
867            X      : UI_Vector (1 .. Sum_Length);
868            Y      : UI_Vector (1 .. Sum_Length);
869            Tmp_UI : UI_Vector (1 .. Sum_Length);
870
871         begin
872            for J in 1 .. Sum_Length - L_Length loop
873               X (J) := 0;
874            end loop;
875
876            X (Sum_Length - L_Length + 1) := abs L_Vec (1);
877
878            for J in 2 .. L_Length loop
879               X (J + (Sum_Length - L_Length)) := L_Vec (J);
880            end loop;
881
882            for J in 1 .. Sum_Length - R_Length loop
883               Y (J) := 0;
884            end loop;
885
886            Y (Sum_Length - R_Length + 1) := abs R_Vec (1);
887
888            for J in 2 .. R_Length loop
889               Y (J + (Sum_Length - R_Length)) := R_Vec (J);
890            end loop;
891
892            if (L_Vec (1) < Int_0) = (R_Vec (1) < Int_0) then
893
894               --  Same sign so just add
895
896               Carry := 0;
897               for J in reverse 1 .. Sum_Length loop
898                  Tmp_Int := X (J) + Y (J) + Carry;
899
900                  if Tmp_Int >= Base then
901                     Tmp_Int := Tmp_Int - Base;
902                     Carry := 1;
903                  else
904                     Carry := 0;
905                  end if;
906
907                  X (J) := Tmp_Int;
908               end loop;
909
910               return Vector_To_Uint (X, L_Vec (1) < Int_0);
911
912            else
913               --  Find which one has bigger magnitude
914
915               if not (X_Bigger or Y_Bigger) then
916                  for J in L_Vec'Range loop
917                     if abs L_Vec (J) > abs R_Vec (J) then
918                        X_Bigger := True;
919                        exit;
920                     elsif abs R_Vec (J) > abs L_Vec (J) then
921                        Y_Bigger := True;
922                        exit;
923                     end if;
924                  end loop;
925               end if;
926
927               --  If they have identical magnitude, just return 0, else swap
928               --  if necessary so that X had the bigger magnitude. Determine
929               --  if result is negative at this time.
930
931               Result_Neg := False;
932
933               if not (X_Bigger or Y_Bigger) then
934                  return Uint_0;
935
936               elsif Y_Bigger then
937                  if R_Vec (1) < Int_0 then
938                     Result_Neg := True;
939                  end if;
940
941                  Tmp_UI := X;
942                  X := Y;
943                  Y := Tmp_UI;
944
945               else
946                  if L_Vec (1) < Int_0 then
947                     Result_Neg := True;
948                  end if;
949               end if;
950
951               --  Subtract Y from the bigger X
952
953               Borrow := 0;
954
955               for J in reverse 1 .. Sum_Length loop
956                  Tmp_Int := X (J) - Y (J) + Borrow;
957
958                  if Tmp_Int < Int_0 then
959                     Tmp_Int := Tmp_Int + Base;
960                     Borrow := -1;
961                  else
962                     Borrow := 0;
963                  end if;
964
965                  X (J) := Tmp_Int;
966               end loop;
967
968               return Vector_To_Uint (X, Result_Neg);
969
970            end if;
971         end;
972      end;
973   end UI_Add;
974
975   --------------------------
976   -- UI_Decimal_Digits_Hi --
977   --------------------------
978
979   function UI_Decimal_Digits_Hi (U : Uint) return Nat is
980   begin
981      --  The maximum value of a "digit" is 32767, which is 5 decimal digits,
982      --  so an N_Digit number could take up to 5 times this number of digits.
983      --  This is certainly too high for large numbers but it is not worth
984      --  worrying about.
985
986      return 5 * N_Digits (U);
987   end UI_Decimal_Digits_Hi;
988
989   --------------------------
990   -- UI_Decimal_Digits_Lo --
991   --------------------------
992
993   function UI_Decimal_Digits_Lo (U : Uint) return Nat is
994   begin
995      --  The maximum value of a "digit" is 32767, which is more than four
996      --  decimal digits, but not a full five digits. The easily computed
997      --  minimum number of decimal digits is thus 1 + 4 * the number of
998      --  digits. This is certainly too low for large numbers but it is not
999      --  worth worrying about.
1000
1001      return 1 + 4 * (N_Digits (U) - 1);
1002   end UI_Decimal_Digits_Lo;
1003
1004   ------------
1005   -- UI_Div --
1006   ------------
1007
1008   function UI_Div (Left : Int; Right : Uint) return Uint is
1009   begin
1010      return UI_Div (UI_From_Int (Left), Right);
1011   end UI_Div;
1012
1013   function UI_Div (Left : Uint; Right : Int) return Uint is
1014   begin
1015      return UI_Div (Left, UI_From_Int (Right));
1016   end UI_Div;
1017
1018   function UI_Div (Left, Right : Uint) return Uint is
1019      Quotient  : Uint;
1020      Remainder : Uint;
1021      pragma Warnings (Off, Remainder);
1022   begin
1023      UI_Div_Rem
1024        (Left, Right,
1025         Quotient, Remainder,
1026         Discard_Remainder => True);
1027      return Quotient;
1028   end UI_Div;
1029
1030   ----------------
1031   -- UI_Div_Rem --
1032   ----------------
1033
1034   procedure UI_Div_Rem
1035     (Left, Right       : Uint;
1036      Quotient          : out Uint;
1037      Remainder         : out Uint;
1038      Discard_Quotient  : Boolean := False;
1039      Discard_Remainder : Boolean := False)
1040   is
1041   begin
1042      pragma Assert (Right /= Uint_0);
1043
1044      Quotient  := No_Uint;
1045      Remainder := No_Uint;
1046
1047      --  Cases where both operands are represented directly
1048
1049      if Direct (Left) and then Direct (Right) then
1050         declare
1051            DV_Left  : constant Int := Direct_Val (Left);
1052            DV_Right : constant Int := Direct_Val (Right);
1053
1054         begin
1055            if not Discard_Quotient then
1056               Quotient := UI_From_Int (DV_Left / DV_Right);
1057            end if;
1058
1059            if not Discard_Remainder then
1060               Remainder := UI_From_Int (DV_Left rem DV_Right);
1061            end if;
1062
1063            return;
1064         end;
1065      end if;
1066
1067      declare
1068         L_Length    : constant Int := N_Digits (Left);
1069         R_Length    : constant Int := N_Digits (Right);
1070         Q_Length    : constant Int := L_Length - R_Length + 1;
1071         L_Vec       : UI_Vector (1 .. L_Length);
1072         R_Vec       : UI_Vector (1 .. R_Length);
1073         D           : Int;
1074         Remainder_I : Int;
1075         Tmp_Divisor : Int;
1076         Carry       : Int;
1077         Tmp_Int     : Int;
1078         Tmp_Dig     : Int;
1079
1080         procedure UI_Div_Vector
1081           (L_Vec     : UI_Vector;
1082            R_Int     : Int;
1083            Quotient  : out UI_Vector;
1084            Remainder : out Int);
1085         pragma Inline (UI_Div_Vector);
1086         --  Specialised variant for case where the divisor is a single digit
1087
1088         procedure UI_Div_Vector
1089           (L_Vec     : UI_Vector;
1090            R_Int     : Int;
1091            Quotient  : out UI_Vector;
1092            Remainder : out Int)
1093         is
1094            Tmp_Int : Int;
1095
1096         begin
1097            Remainder := 0;
1098            for J in L_Vec'Range loop
1099               Tmp_Int := Remainder * Base + abs L_Vec (J);
1100               Quotient (Quotient'First + J - L_Vec'First) := Tmp_Int / R_Int;
1101               Remainder := Tmp_Int rem R_Int;
1102            end loop;
1103
1104            if L_Vec (L_Vec'First) < Int_0 then
1105               Remainder := -Remainder;
1106            end if;
1107         end UI_Div_Vector;
1108
1109      --  Start of processing for UI_Div_Rem
1110
1111      begin
1112         --  Result is zero if left operand is shorter than right
1113
1114         if L_Length < R_Length then
1115            if not Discard_Quotient then
1116               Quotient := Uint_0;
1117            end if;
1118
1119            if not Discard_Remainder then
1120               Remainder := Left;
1121            end if;
1122
1123            return;
1124         end if;
1125
1126         Init_Operand (Left, L_Vec);
1127         Init_Operand (Right, R_Vec);
1128
1129         --  Case of right operand is single digit. Here we can simply divide
1130         --  each digit of the left operand by the divisor, from most to least
1131         --  significant, carrying the remainder to the next digit (just like
1132         --  ordinary long division by hand).
1133
1134         if R_Length = Int_1 then
1135            Tmp_Divisor := abs R_Vec (1);
1136
1137            declare
1138               Quotient_V : UI_Vector (1 .. L_Length);
1139
1140            begin
1141               UI_Div_Vector (L_Vec, Tmp_Divisor, Quotient_V, Remainder_I);
1142
1143               if not Discard_Quotient then
1144                  Quotient :=
1145                    Vector_To_Uint
1146                      (Quotient_V, (L_Vec (1) < Int_0 xor R_Vec (1) < Int_0));
1147               end if;
1148
1149               if not Discard_Remainder then
1150                  Remainder := UI_From_Int (Remainder_I);
1151               end if;
1152
1153               return;
1154            end;
1155         end if;
1156
1157         --  The possible simple cases have been exhausted. Now turn to the
1158         --  algorithm D from the section of Knuth mentioned at the top of
1159         --  this package.
1160
1161         Algorithm_D : declare
1162            Dividend     : UI_Vector (1 .. L_Length + 1);
1163            Divisor      : UI_Vector (1 .. R_Length);
1164            Quotient_V   : UI_Vector (1 .. Q_Length);
1165            Divisor_Dig1 : Int;
1166            Divisor_Dig2 : Int;
1167            Q_Guess      : Int;
1168            R_Guess      : Int;
1169
1170         begin
1171            --  [ NORMALIZE ] (step D1 in the algorithm). First calculate the
1172            --  scale d, and then multiply Left and Right (u and v in the book)
1173            --  by d to get the dividend and divisor to work with.
1174
1175            D := Base / (abs R_Vec (1) + 1);
1176
1177            Dividend (1) := 0;
1178            Dividend (2) := abs L_Vec (1);
1179
1180            for J in 3 .. L_Length + Int_1 loop
1181               Dividend (J) := L_Vec (J - 1);
1182            end loop;
1183
1184            Divisor (1) := abs R_Vec (1);
1185
1186            for J in Int_2 .. R_Length loop
1187               Divisor (J) := R_Vec (J);
1188            end loop;
1189
1190            if D > Int_1 then
1191
1192               --  Multiply Dividend by d
1193
1194               Carry := 0;
1195               for J in reverse Dividend'Range loop
1196                  Tmp_Int      := Dividend (J) * D + Carry;
1197                  Dividend (J) := Tmp_Int rem Base;
1198                  Carry        := Tmp_Int / Base;
1199               end loop;
1200
1201               --  Multiply Divisor by d
1202
1203               Carry := 0;
1204               for J in reverse Divisor'Range loop
1205                  Tmp_Int      := Divisor (J) * D + Carry;
1206                  Divisor (J)  := Tmp_Int rem Base;
1207                  Carry        := Tmp_Int / Base;
1208               end loop;
1209            end if;
1210
1211            --  Main loop of long division algorithm
1212
1213            Divisor_Dig1 := Divisor (1);
1214            Divisor_Dig2 := Divisor (2);
1215
1216            for J in Quotient_V'Range loop
1217
1218               --  [ CALCULATE Q (hat) ] (step D3 in the algorithm)
1219
1220               --  Note: this version of step D3 is from the original published
1221               --  algorithm, which is known to have a bug causing overflows.
1222               --  See: http://www-cs-faculty.stanford.edu/~uno/err2-2e.ps.gz
1223               --  and http://www-cs-faculty.stanford.edu/~uno/all2-pre.ps.gz.
1224               --  The code below is the fixed version of this step.
1225
1226               Tmp_Int := Dividend (J) * Base + Dividend (J + 1);
1227
1228               --  Initial guess
1229
1230               Q_Guess := Tmp_Int / Divisor_Dig1;
1231               R_Guess := Tmp_Int rem Divisor_Dig1;
1232
1233               --  Refine the guess
1234
1235               while Q_Guess >= Base
1236                 or else Divisor_Dig2 * Q_Guess >
1237                           R_Guess * Base + Dividend (J + 2)
1238               loop
1239                  Q_Guess := Q_Guess - 1;
1240                  R_Guess := R_Guess + Divisor_Dig1;
1241                  exit when R_Guess >= Base;
1242               end loop;
1243
1244               --  [ MULTIPLY & SUBTRACT ] (step D4). Q_Guess * Divisor is
1245               --  subtracted from the remaining dividend.
1246
1247               Carry := 0;
1248               for K in reverse Divisor'Range loop
1249                  Tmp_Int := Dividend (J + K) - Q_Guess * Divisor (K) + Carry;
1250                  Tmp_Dig := Tmp_Int rem Base;
1251                  Carry   := Tmp_Int / Base;
1252
1253                  if Tmp_Dig < Int_0 then
1254                     Tmp_Dig := Tmp_Dig + Base;
1255                     Carry   := Carry - 1;
1256                  end if;
1257
1258                  Dividend (J + K) := Tmp_Dig;
1259               end loop;
1260
1261               Dividend (J) := Dividend (J) + Carry;
1262
1263               --  [ TEST REMAINDER ] & [ ADD BACK ] (steps D5 and D6)
1264
1265               --  Here there is a slight difference from the book: the last
1266               --  carry is always added in above and below (cancelling each
1267               --  other). In fact the dividend going negative is used as
1268               --  the test.
1269
1270               --  If the Dividend went negative, then Q_Guess was off by
1271               --  one, so it is decremented, and the divisor is added back
1272               --  into the relevant portion of the dividend.
1273
1274               if Dividend (J) < Int_0 then
1275                  Q_Guess := Q_Guess - 1;
1276
1277                  Carry := 0;
1278                  for K in reverse Divisor'Range loop
1279                     Tmp_Int := Dividend (J + K) + Divisor (K) + Carry;
1280
1281                     if Tmp_Int >= Base then
1282                        Tmp_Int := Tmp_Int - Base;
1283                        Carry := 1;
1284                     else
1285                        Carry := 0;
1286                     end if;
1287
1288                     Dividend (J + K) := Tmp_Int;
1289                  end loop;
1290
1291                  Dividend (J) := Dividend (J) + Carry;
1292               end if;
1293
1294               --  Finally we can get the next quotient digit
1295
1296               Quotient_V (J) := Q_Guess;
1297            end loop;
1298
1299            --  [ UNNORMALIZE ] (step D8)
1300
1301            if not Discard_Quotient then
1302               Quotient := Vector_To_Uint
1303                 (Quotient_V, (L_Vec (1) < Int_0 xor R_Vec (1) < Int_0));
1304            end if;
1305
1306            if not Discard_Remainder then
1307               declare
1308                  Remainder_V : UI_Vector (1 .. R_Length);
1309                  Discard_Int : Int;
1310                  pragma Warnings (Off, Discard_Int);
1311               begin
1312                  UI_Div_Vector
1313                    (Dividend (Dividend'Last - R_Length + 1 .. Dividend'Last),
1314                     D,
1315                     Remainder_V, Discard_Int);
1316                  Remainder := Vector_To_Uint (Remainder_V, L_Vec (1) < Int_0);
1317               end;
1318            end if;
1319         end Algorithm_D;
1320      end;
1321   end UI_Div_Rem;
1322
1323   ------------
1324   -- UI_Eq --
1325   ------------
1326
1327   function UI_Eq (Left : Int; Right : Uint) return Boolean is
1328   begin
1329      return not UI_Ne (UI_From_Int (Left), Right);
1330   end UI_Eq;
1331
1332   function UI_Eq (Left : Uint; Right : Int) return Boolean is
1333   begin
1334      return not UI_Ne (Left, UI_From_Int (Right));
1335   end UI_Eq;
1336
1337   function UI_Eq (Left : Uint; Right : Uint) return Boolean is
1338   begin
1339      return not UI_Ne (Left, Right);
1340   end UI_Eq;
1341
1342   --------------
1343   -- UI_Expon --
1344   --------------
1345
1346   function UI_Expon (Left : Int; Right : Uint) return Uint is
1347   begin
1348      return UI_Expon (UI_From_Int (Left), Right);
1349   end UI_Expon;
1350
1351   function UI_Expon (Left : Uint; Right : Int) return Uint is
1352   begin
1353      return UI_Expon (Left, UI_From_Int (Right));
1354   end UI_Expon;
1355
1356   function UI_Expon (Left : Int; Right : Int) return Uint is
1357   begin
1358      return UI_Expon (UI_From_Int (Left), UI_From_Int (Right));
1359   end UI_Expon;
1360
1361   function UI_Expon (Left : Uint; Right : Uint) return Uint is
1362   begin
1363      pragma Assert (Right >= Uint_0);
1364
1365      --  Any value raised to power of 0 is 1
1366
1367      if Right = Uint_0 then
1368         return Uint_1;
1369
1370      --  0 to any positive power is 0
1371
1372      elsif Left = Uint_0 then
1373         return Uint_0;
1374
1375      --  1 to any power is 1
1376
1377      elsif Left = Uint_1 then
1378         return Uint_1;
1379
1380      --  Any value raised to power of 1 is that value
1381
1382      elsif Right = Uint_1 then
1383         return Left;
1384
1385      --  Cases which can be done by table lookup
1386
1387      elsif Right <= Uint_64 then
1388
1389         --  2 ** N for N in 2 .. 64
1390
1391         if Left = Uint_2 then
1392            declare
1393               Right_Int : constant Int := Direct_Val (Right);
1394
1395            begin
1396               if Right_Int > UI_Power_2_Set then
1397                  for J in UI_Power_2_Set + Int_1 .. Right_Int loop
1398                     UI_Power_2 (J) := UI_Power_2 (J - Int_1) * Int_2;
1399                     Uints_Min := Uints.Last;
1400                     Udigits_Min := Udigits.Last;
1401                  end loop;
1402
1403                  UI_Power_2_Set := Right_Int;
1404               end if;
1405
1406               return UI_Power_2 (Right_Int);
1407            end;
1408
1409         --  10 ** N for N in 2 .. 64
1410
1411         elsif Left = Uint_10 then
1412            declare
1413               Right_Int : constant Int := Direct_Val (Right);
1414
1415            begin
1416               if Right_Int > UI_Power_10_Set then
1417                  for J in UI_Power_10_Set + Int_1 .. Right_Int loop
1418                     UI_Power_10 (J) := UI_Power_10 (J - Int_1) * Int (10);
1419                     Uints_Min := Uints.Last;
1420                     Udigits_Min := Udigits.Last;
1421                  end loop;
1422
1423                  UI_Power_10_Set := Right_Int;
1424               end if;
1425
1426               return UI_Power_10 (Right_Int);
1427            end;
1428         end if;
1429      end if;
1430
1431      --  If we fall through, then we have the general case (see Knuth 4.6.3)
1432
1433      declare
1434         N       : Uint := Right;
1435         Squares : Uint := Left;
1436         Result  : Uint := Uint_1;
1437         M       : constant Uintp.Save_Mark := Uintp.Mark;
1438
1439      begin
1440         loop
1441            if (Least_Sig_Digit (N) mod Int_2) = Int_1 then
1442               Result := Result * Squares;
1443            end if;
1444
1445            N := N / Uint_2;
1446            exit when N = Uint_0;
1447            Squares := Squares *  Squares;
1448         end loop;
1449
1450         Uintp.Release_And_Save (M, Result);
1451         return Result;
1452      end;
1453   end UI_Expon;
1454
1455   ----------------
1456   -- UI_From_CC --
1457   ----------------
1458
1459   function UI_From_CC (Input : Char_Code) return Uint is
1460   begin
1461      return UI_From_Int (Int (Input));
1462   end UI_From_CC;
1463
1464   -----------------
1465   -- UI_From_Int --
1466   -----------------
1467
1468   function UI_From_Int (Input : Int) return Uint is
1469      U : Uint;
1470
1471   begin
1472      if Min_Direct <= Input and then Input <= Max_Direct then
1473         return Uint (Int (Uint_Direct_Bias) + Input);
1474      end if;
1475
1476      --  If already in the hash table, return entry
1477
1478      U := UI_Ints.Get (Input);
1479
1480      if U /= No_Uint then
1481         return U;
1482      end if;
1483
1484      --  For values of larger magnitude, compute digits into a vector and call
1485      --  Vector_To_Uint.
1486
1487      declare
1488         Max_For_Int : constant := 3;
1489         --  Base is defined so that 3 Uint digits is sufficient to hold the
1490         --  largest possible Int value.
1491
1492         V : UI_Vector (1 .. Max_For_Int);
1493
1494         Temp_Integer : Int := Input;
1495
1496      begin
1497         for J in reverse V'Range loop
1498            V (J) := abs (Temp_Integer rem Base);
1499            Temp_Integer := Temp_Integer / Base;
1500         end loop;
1501
1502         U := Vector_To_Uint (V, Input < Int_0);
1503         UI_Ints.Set (Input, U);
1504         Uints_Min := Uints.Last;
1505         Udigits_Min := Udigits.Last;
1506         return U;
1507      end;
1508   end UI_From_Int;
1509
1510   ------------
1511   -- UI_GCD --
1512   ------------
1513
1514   --  Lehmer's algorithm for GCD
1515
1516   --  The idea is to avoid using multiple precision arithmetic wherever
1517   --  possible, substituting Int arithmetic instead. See Knuth volume II,
1518   --  Algorithm L (page 329).
1519
1520   --  We use the same notation as Knuth (U_Hat standing for the obvious!)
1521
1522   function UI_GCD (Uin, Vin : Uint) return Uint is
1523      U, V : Uint;
1524      --  Copies of Uin and Vin
1525
1526      U_Hat, V_Hat : Int;
1527      --  The most Significant digits of U,V
1528
1529      A, B, C, D, T, Q, Den1, Den2 : Int;
1530
1531      Tmp_UI : Uint;
1532      Marks  : constant Uintp.Save_Mark := Uintp.Mark;
1533      Iterations : Integer := 0;
1534
1535   begin
1536      pragma Assert (Uin >= Vin);
1537      pragma Assert (Vin >= Uint_0);
1538
1539      U := Uin;
1540      V := Vin;
1541
1542      loop
1543         Iterations := Iterations + 1;
1544
1545         if Direct (V) then
1546            if V = Uint_0 then
1547               return U;
1548            else
1549               return
1550                 UI_From_Int (GCD (Direct_Val (V), UI_To_Int (U rem V)));
1551            end if;
1552         end if;
1553
1554         Most_Sig_2_Digits (U, V, U_Hat, V_Hat);
1555         A := 1;
1556         B := 0;
1557         C := 0;
1558         D := 1;
1559
1560         loop
1561            --  We might overflow and get division by zero here. This just
1562            --  means we cannot take the single precision step
1563
1564            Den1 := V_Hat + C;
1565            Den2 := V_Hat + D;
1566            exit when Den1 = Int_0 or else Den2 = Int_0;
1567
1568            --  Compute Q, the trial quotient
1569
1570            Q := (U_Hat + A) / Den1;
1571
1572            exit when Q /= ((U_Hat + B) / Den2);
1573
1574            --  A single precision step Euclid step will give same answer as a
1575            --  multiprecision one.
1576
1577            T := A - (Q * C);
1578            A := C;
1579            C := T;
1580
1581            T := B - (Q * D);
1582            B := D;
1583            D := T;
1584
1585            T := U_Hat - (Q * V_Hat);
1586            U_Hat := V_Hat;
1587            V_Hat := T;
1588
1589         end loop;
1590
1591         --  Take a multiprecision Euclid step
1592
1593         if B = Int_0 then
1594
1595            --  No single precision steps take a regular Euclid step
1596
1597            Tmp_UI := U rem V;
1598            U := V;
1599            V := Tmp_UI;
1600
1601         else
1602            --  Use prior single precision steps to compute this Euclid step
1603
1604            --  For constructs such as:
1605            --  sqrt_2: constant :=  1.41421_35623_73095_04880_16887_24209_698;
1606            --  sqrt_eps: constant long_float := long_float( 1.0 / sqrt_2)
1607            --    ** long_float'machine_mantissa;
1608            --
1609            --  we spend 80% of our time working on this step. Perhaps we need
1610            --  a special case Int / Uint dot product to speed things up. ???
1611
1612            --  Alternatively we could increase the single precision iterations
1613            --  to handle Uint's of some small size ( <5 digits?). Then we
1614            --  would have more iterations on small Uint. On the code above, we
1615            --  only get 5 (on average) single precision iterations per large
1616            --  iteration. ???
1617
1618            Tmp_UI := (UI_From_Int (A) * U) + (UI_From_Int (B) * V);
1619            V := (UI_From_Int (C) * U) + (UI_From_Int (D) * V);
1620            U := Tmp_UI;
1621         end if;
1622
1623         --  If the operands are very different in magnitude, the loop will
1624         --  generate large amounts of short-lived data, which it is worth
1625         --  removing periodically.
1626
1627         if Iterations > 100 then
1628            Release_And_Save (Marks, U, V);
1629            Iterations := 0;
1630         end if;
1631      end loop;
1632   end UI_GCD;
1633
1634   ------------
1635   -- UI_Ge --
1636   ------------
1637
1638   function UI_Ge (Left : Int; Right : Uint) return Boolean is
1639   begin
1640      return not UI_Lt (UI_From_Int (Left), Right);
1641   end UI_Ge;
1642
1643   function UI_Ge (Left : Uint; Right : Int) return Boolean is
1644   begin
1645      return not UI_Lt (Left, UI_From_Int (Right));
1646   end UI_Ge;
1647
1648   function UI_Ge (Left : Uint; Right : Uint) return Boolean is
1649   begin
1650      return not UI_Lt (Left, Right);
1651   end UI_Ge;
1652
1653   ------------
1654   -- UI_Gt --
1655   ------------
1656
1657   function UI_Gt (Left : Int; Right : Uint) return Boolean is
1658   begin
1659      return UI_Lt (Right, UI_From_Int (Left));
1660   end UI_Gt;
1661
1662   function UI_Gt (Left : Uint; Right : Int) return Boolean is
1663   begin
1664      return UI_Lt (UI_From_Int (Right), Left);
1665   end UI_Gt;
1666
1667   function UI_Gt (Left : Uint; Right : Uint) return Boolean is
1668   begin
1669      return UI_Lt (Left => Right, Right => Left);
1670   end UI_Gt;
1671
1672   ---------------
1673   -- UI_Image --
1674   ---------------
1675
1676   procedure UI_Image (Input : Uint; Format : UI_Format := Auto) is
1677   begin
1678      Image_Out (Input, True, Format);
1679   end UI_Image;
1680
1681   -------------------------
1682   -- UI_Is_In_Int_Range --
1683   -------------------------
1684
1685   function UI_Is_In_Int_Range (Input : Uint) return Boolean is
1686   begin
1687      --  Make sure we don't get called before Initialize
1688
1689      pragma Assert (Uint_Int_First /= Uint_0);
1690
1691      if Direct (Input) then
1692         return True;
1693      else
1694         return Input >= Uint_Int_First
1695           and then Input <= Uint_Int_Last;
1696      end if;
1697   end UI_Is_In_Int_Range;
1698
1699   ------------
1700   -- UI_Le --
1701   ------------
1702
1703   function UI_Le (Left : Int; Right : Uint) return Boolean is
1704   begin
1705      return not UI_Lt (Right, UI_From_Int (Left));
1706   end UI_Le;
1707
1708   function UI_Le (Left : Uint; Right : Int) return Boolean is
1709   begin
1710      return not UI_Lt (UI_From_Int (Right), Left);
1711   end UI_Le;
1712
1713   function UI_Le (Left : Uint; Right : Uint) return Boolean is
1714   begin
1715      return not UI_Lt (Left => Right, Right => Left);
1716   end UI_Le;
1717
1718   ------------
1719   -- UI_Lt --
1720   ------------
1721
1722   function UI_Lt (Left : Int; Right : Uint) return Boolean is
1723   begin
1724      return UI_Lt (UI_From_Int (Left), Right);
1725   end UI_Lt;
1726
1727   function UI_Lt (Left : Uint; Right : Int) return Boolean is
1728   begin
1729      return UI_Lt (Left, UI_From_Int (Right));
1730   end UI_Lt;
1731
1732   function UI_Lt (Left : Uint; Right : Uint) return Boolean is
1733   begin
1734      --  Quick processing for identical arguments
1735
1736      if Int (Left) = Int (Right) then
1737         return False;
1738
1739      --  Quick processing for both arguments directly represented
1740
1741      elsif Direct (Left) and then Direct (Right) then
1742         return Int (Left) < Int (Right);
1743
1744      --  At least one argument is more than one digit long
1745
1746      else
1747         declare
1748            L_Length : constant Int := N_Digits (Left);
1749            R_Length : constant Int := N_Digits (Right);
1750
1751            L_Vec : UI_Vector (1 .. L_Length);
1752            R_Vec : UI_Vector (1 .. R_Length);
1753
1754         begin
1755            Init_Operand (Left, L_Vec);
1756            Init_Operand (Right, R_Vec);
1757
1758            if L_Vec (1) < Int_0 then
1759
1760               --  First argument negative, second argument non-negative
1761
1762               if R_Vec (1) >= Int_0 then
1763                  return True;
1764
1765               --  Both arguments negative
1766
1767               else
1768                  if L_Length /= R_Length then
1769                     return L_Length > R_Length;
1770
1771                  elsif L_Vec (1) /= R_Vec (1) then
1772                     return L_Vec (1) < R_Vec (1);
1773
1774                  else
1775                     for J in 2 .. L_Vec'Last loop
1776                        if L_Vec (J) /= R_Vec (J) then
1777                           return L_Vec (J) > R_Vec (J);
1778                        end if;
1779                     end loop;
1780
1781                     return False;
1782                  end if;
1783               end if;
1784
1785            else
1786               --  First argument non-negative, second argument negative
1787
1788               if R_Vec (1) < Int_0 then
1789                  return False;
1790
1791               --  Both arguments non-negative
1792
1793               else
1794                  if L_Length /= R_Length then
1795                     return L_Length < R_Length;
1796                  else
1797                     for J in L_Vec'Range loop
1798                        if L_Vec (J) /= R_Vec (J) then
1799                           return L_Vec (J) < R_Vec (J);
1800                        end if;
1801                     end loop;
1802
1803                     return False;
1804                  end if;
1805               end if;
1806            end if;
1807         end;
1808      end if;
1809   end UI_Lt;
1810
1811   ------------
1812   -- UI_Max --
1813   ------------
1814
1815   function UI_Max (Left : Int; Right : Uint) return Uint is
1816   begin
1817      return UI_Max (UI_From_Int (Left), Right);
1818   end UI_Max;
1819
1820   function UI_Max (Left : Uint; Right : Int) return Uint is
1821   begin
1822      return UI_Max (Left, UI_From_Int (Right));
1823   end UI_Max;
1824
1825   function UI_Max (Left : Uint; Right : Uint) return Uint is
1826   begin
1827      if Left >= Right then
1828         return Left;
1829      else
1830         return Right;
1831      end if;
1832   end UI_Max;
1833
1834   ------------
1835   -- UI_Min --
1836   ------------
1837
1838   function UI_Min (Left : Int; Right : Uint) return Uint is
1839   begin
1840      return UI_Min (UI_From_Int (Left), Right);
1841   end UI_Min;
1842
1843   function UI_Min (Left : Uint; Right : Int) return Uint is
1844   begin
1845      return UI_Min (Left, UI_From_Int (Right));
1846   end UI_Min;
1847
1848   function UI_Min (Left : Uint; Right : Uint) return Uint is
1849   begin
1850      if Left <= Right then
1851         return Left;
1852      else
1853         return Right;
1854      end if;
1855   end UI_Min;
1856
1857   -------------
1858   -- UI_Mod --
1859   -------------
1860
1861   function UI_Mod (Left : Int; Right : Uint) return Uint is
1862   begin
1863      return UI_Mod (UI_From_Int (Left), Right);
1864   end UI_Mod;
1865
1866   function UI_Mod (Left : Uint; Right : Int) return Uint is
1867   begin
1868      return UI_Mod (Left, UI_From_Int (Right));
1869   end UI_Mod;
1870
1871   function UI_Mod (Left : Uint; Right : Uint) return Uint is
1872      Urem : constant Uint := Left rem Right;
1873
1874   begin
1875      if (Left < Uint_0) = (Right < Uint_0)
1876        or else Urem = Uint_0
1877      then
1878         return Urem;
1879      else
1880         return Right + Urem;
1881      end if;
1882   end UI_Mod;
1883
1884   -------------------------------
1885   -- UI_Modular_Exponentiation --
1886   -------------------------------
1887
1888   function UI_Modular_Exponentiation
1889     (B      : Uint;
1890      E      : Uint;
1891      Modulo : Uint) return Uint
1892   is
1893      M : constant Save_Mark := Mark;
1894
1895      Result   : Uint := Uint_1;
1896      Base     : Uint := B;
1897      Exponent : Uint := E;
1898
1899   begin
1900      while Exponent /= Uint_0 loop
1901         if Least_Sig_Digit (Exponent) rem Int'(2) = Int'(1) then
1902            Result := (Result * Base) rem Modulo;
1903         end if;
1904
1905         Exponent := Exponent / Uint_2;
1906         Base := (Base * Base) rem Modulo;
1907      end loop;
1908
1909      Release_And_Save (M, Result);
1910      return Result;
1911   end UI_Modular_Exponentiation;
1912
1913   ------------------------
1914   -- UI_Modular_Inverse --
1915   ------------------------
1916
1917   function UI_Modular_Inverse (N : Uint; Modulo : Uint) return Uint is
1918      M : constant Save_Mark := Mark;
1919      U : Uint;
1920      V : Uint;
1921      Q : Uint;
1922      R : Uint;
1923      X : Uint;
1924      Y : Uint;
1925      T : Uint;
1926      S : Int := 1;
1927
1928   begin
1929      U := Modulo;
1930      V := N;
1931
1932      X := Uint_1;
1933      Y := Uint_0;
1934
1935      loop
1936         UI_Div_Rem (U, V, Quotient => Q, Remainder => R);
1937
1938         U := V;
1939         V := R;
1940
1941         T := X;
1942         X := Y + Q * X;
1943         Y := T;
1944         S := -S;
1945
1946         exit when R = Uint_1;
1947      end loop;
1948
1949      if S = Int'(-1) then
1950         X := Modulo - X;
1951      end if;
1952
1953      Release_And_Save (M, X);
1954      return X;
1955   end UI_Modular_Inverse;
1956
1957   ------------
1958   -- UI_Mul --
1959   ------------
1960
1961   function UI_Mul (Left : Int; Right : Uint) return Uint is
1962   begin
1963      return UI_Mul (UI_From_Int (Left), Right);
1964   end UI_Mul;
1965
1966   function UI_Mul (Left : Uint; Right : Int) return Uint is
1967   begin
1968      return UI_Mul (Left, UI_From_Int (Right));
1969   end UI_Mul;
1970
1971   function UI_Mul (Left : Uint; Right : Uint) return Uint is
1972   begin
1973      --  Case where product fits in the range of a 32-bit integer
1974
1975      if Int (Left)  <= Int (Uint_Max_Simple_Mul)
1976           and then
1977         Int (Right) <= Int (Uint_Max_Simple_Mul)
1978      then
1979         return UI_From_Int (Direct_Val (Left) * Direct_Val (Right));
1980      end if;
1981
1982      --  Otherwise we have the general case (Algorithm M in Knuth)
1983
1984      declare
1985         L_Length : constant Int := N_Digits (Left);
1986         R_Length : constant Int := N_Digits (Right);
1987         L_Vec    : UI_Vector (1 .. L_Length);
1988         R_Vec    : UI_Vector (1 .. R_Length);
1989         Neg      : Boolean;
1990
1991      begin
1992         Init_Operand (Left, L_Vec);
1993         Init_Operand (Right, R_Vec);
1994         Neg := (L_Vec (1) < Int_0) xor (R_Vec (1) < Int_0);
1995         L_Vec (1) := abs (L_Vec (1));
1996         R_Vec (1) := abs (R_Vec (1));
1997
1998         Algorithm_M : declare
1999            Product : UI_Vector (1 .. L_Length + R_Length);
2000            Tmp_Sum : Int;
2001            Carry   : Int;
2002
2003         begin
2004            for J in Product'Range loop
2005               Product (J) := 0;
2006            end loop;
2007
2008            for J in reverse R_Vec'Range loop
2009               Carry := 0;
2010               for K in reverse L_Vec'Range loop
2011                  Tmp_Sum :=
2012                    L_Vec (K) * R_Vec (J) + Product (J + K) + Carry;
2013                  Product (J + K) := Tmp_Sum rem Base;
2014                  Carry := Tmp_Sum / Base;
2015               end loop;
2016
2017               Product (J) := Carry;
2018            end loop;
2019
2020            return Vector_To_Uint (Product, Neg);
2021         end Algorithm_M;
2022      end;
2023   end UI_Mul;
2024
2025   ------------
2026   -- UI_Ne --
2027   ------------
2028
2029   function UI_Ne (Left : Int; Right : Uint) return Boolean is
2030   begin
2031      return UI_Ne (UI_From_Int (Left), Right);
2032   end UI_Ne;
2033
2034   function UI_Ne (Left : Uint; Right : Int) return Boolean is
2035   begin
2036      return UI_Ne (Left, UI_From_Int (Right));
2037   end UI_Ne;
2038
2039   function UI_Ne (Left : Uint; Right : Uint) return Boolean is
2040   begin
2041      --  Quick processing for identical arguments. Note that this takes
2042      --  care of the case of two No_Uint arguments.
2043
2044      if Int (Left) = Int (Right) then
2045         return False;
2046      end if;
2047
2048      --  See if left operand directly represented
2049
2050      if Direct (Left) then
2051
2052         --  If right operand directly represented then compare
2053
2054         if Direct (Right) then
2055            return Int (Left) /= Int (Right);
2056
2057         --  Left operand directly represented, right not, must be unequal
2058
2059         else
2060            return True;
2061         end if;
2062
2063      --  Right operand directly represented, left not, must be unequal
2064
2065      elsif Direct (Right) then
2066         return True;
2067      end if;
2068
2069      --  Otherwise both multi-word, do comparison
2070
2071      declare
2072         Size      : constant Int := N_Digits (Left);
2073         Left_Loc  : Int;
2074         Right_Loc : Int;
2075
2076      begin
2077         if Size /= N_Digits (Right) then
2078            return True;
2079         end if;
2080
2081         Left_Loc  := Uints.Table (Left).Loc;
2082         Right_Loc := Uints.Table (Right).Loc;
2083
2084         for J in Int_0 .. Size - Int_1 loop
2085            if Udigits.Table (Left_Loc + J) /=
2086               Udigits.Table (Right_Loc + J)
2087            then
2088               return True;
2089            end if;
2090         end loop;
2091
2092         return False;
2093      end;
2094   end UI_Ne;
2095
2096   ----------------
2097   -- UI_Negate --
2098   ----------------
2099
2100   function UI_Negate (Right : Uint) return Uint is
2101   begin
2102      --  Case where input is directly represented. Note that since the range
2103      --  of Direct values is non-symmetrical, the result may not be directly
2104      --  represented, this is taken care of in UI_From_Int.
2105
2106      if Direct (Right) then
2107         return UI_From_Int (-Direct_Val (Right));
2108
2109      --  Full processing for multi-digit case. Note that we cannot just copy
2110      --  the value to the end of the table negating the first digit, since the
2111      --  range of Direct values is non-symmetrical, so we can have a negative
2112      --  value that is not Direct whose negation can be represented directly.
2113
2114      else
2115         declare
2116            R_Length : constant Int := N_Digits (Right);
2117            R_Vec    : UI_Vector (1 .. R_Length);
2118            Neg      : Boolean;
2119
2120         begin
2121            Init_Operand (Right, R_Vec);
2122            Neg := R_Vec (1) > Int_0;
2123            R_Vec (1) := abs R_Vec (1);
2124            return Vector_To_Uint (R_Vec, Neg);
2125         end;
2126      end if;
2127   end UI_Negate;
2128
2129   -------------
2130   -- UI_Rem --
2131   -------------
2132
2133   function UI_Rem (Left : Int; Right : Uint) return Uint is
2134   begin
2135      return UI_Rem (UI_From_Int (Left), Right);
2136   end UI_Rem;
2137
2138   function UI_Rem (Left : Uint; Right : Int) return Uint is
2139   begin
2140      return UI_Rem (Left, UI_From_Int (Right));
2141   end UI_Rem;
2142
2143   function UI_Rem (Left, Right : Uint) return Uint is
2144      Remainder : Uint;
2145      Quotient  : Uint;
2146      pragma Warnings (Off, Quotient);
2147
2148   begin
2149      pragma Assert (Right /= Uint_0);
2150
2151      if Direct (Right) and then Direct (Left) then
2152         return UI_From_Int (Direct_Val (Left) rem Direct_Val (Right));
2153
2154      else
2155         UI_Div_Rem
2156           (Left, Right, Quotient, Remainder, Discard_Quotient => True);
2157         return Remainder;
2158      end if;
2159   end UI_Rem;
2160
2161   ------------
2162   -- UI_Sub --
2163   ------------
2164
2165   function UI_Sub (Left : Int; Right : Uint) return Uint is
2166   begin
2167      return UI_Add (Left, -Right);
2168   end UI_Sub;
2169
2170   function UI_Sub (Left : Uint; Right : Int) return Uint is
2171   begin
2172      return UI_Add (Left, -Right);
2173   end UI_Sub;
2174
2175   function UI_Sub (Left : Uint; Right : Uint) return Uint is
2176   begin
2177      if Direct (Left) and then Direct (Right) then
2178         return UI_From_Int (Direct_Val (Left) - Direct_Val (Right));
2179      else
2180         return UI_Add (Left, -Right);
2181      end if;
2182   end UI_Sub;
2183
2184   --------------
2185   -- UI_To_CC --
2186   --------------
2187
2188   function UI_To_CC (Input : Uint) return Char_Code is
2189   begin
2190      if Direct (Input) then
2191         return Char_Code (Direct_Val (Input));
2192
2193      --  Case of input is more than one digit
2194
2195      else
2196         declare
2197            In_Length : constant Int := N_Digits (Input);
2198            In_Vec    : UI_Vector (1 .. In_Length);
2199            Ret_CC    : Char_Code;
2200
2201         begin
2202            Init_Operand (Input, In_Vec);
2203
2204            --  We assume value is positive
2205
2206            Ret_CC := 0;
2207            for Idx in In_Vec'Range loop
2208               Ret_CC := Ret_CC * Char_Code (Base) +
2209                                  Char_Code (abs In_Vec (Idx));
2210            end loop;
2211
2212            return Ret_CC;
2213         end;
2214      end if;
2215   end UI_To_CC;
2216
2217   ----------------
2218   -- UI_To_Int --
2219   ----------------
2220
2221   function UI_To_Int (Input : Uint) return Int is
2222      pragma Assert (Input /= No_Uint);
2223
2224   begin
2225      if Direct (Input) then
2226         return Direct_Val (Input);
2227
2228      --  Case of input is more than one digit
2229
2230      else
2231         declare
2232            In_Length : constant Int := N_Digits (Input);
2233            In_Vec    : UI_Vector (1 .. In_Length);
2234            Ret_Int   : Int;
2235
2236         begin
2237            --  Uints of more than one digit could be outside the range for
2238            --  Ints. Caller should have checked for this if not certain.
2239            --  Fatal error to attempt to convert from value outside Int'Range.
2240
2241            pragma Assert (UI_Is_In_Int_Range (Input));
2242
2243            --  Otherwise, proceed ahead, we are OK
2244
2245            Init_Operand (Input, In_Vec);
2246            Ret_Int := 0;
2247
2248            --  Calculate -|Input| and then negates if value is positive. This
2249            --  handles our current definition of Int (based on 2s complement).
2250            --  Is it secure enough???
2251
2252            for Idx in In_Vec'Range loop
2253               Ret_Int := Ret_Int * Base - abs In_Vec (Idx);
2254            end loop;
2255
2256            if In_Vec (1) < Int_0 then
2257               return Ret_Int;
2258            else
2259               return -Ret_Int;
2260            end if;
2261         end;
2262      end if;
2263   end UI_To_Int;
2264
2265   --------------
2266   -- UI_Write --
2267   --------------
2268
2269   procedure UI_Write (Input : Uint; Format : UI_Format := Auto) is
2270   begin
2271      Image_Out (Input, False, Format);
2272   end UI_Write;
2273
2274   ---------------------
2275   -- Vector_To_Uint --
2276   ---------------------
2277
2278   function Vector_To_Uint
2279     (In_Vec   : UI_Vector;
2280      Negative : Boolean)
2281      return     Uint
2282   is
2283      Size : Int;
2284      Val  : Int;
2285
2286   begin
2287      --  The vector can contain leading zeros. These are not stored in the
2288      --  table, so loop through the vector looking for first non-zero digit
2289
2290      for J in In_Vec'Range loop
2291         if In_Vec (J) /= Int_0 then
2292
2293            --  The length of the value is the length of the rest of the vector
2294
2295            Size := In_Vec'Last - J + 1;
2296
2297            --  One digit value can always be represented directly
2298
2299            if Size = Int_1 then
2300               if Negative then
2301                  return Uint (Int (Uint_Direct_Bias) - In_Vec (J));
2302               else
2303                  return Uint (Int (Uint_Direct_Bias) + In_Vec (J));
2304               end if;
2305
2306            --  Positive two digit values may be in direct representation range
2307
2308            elsif Size = Int_2 and then not Negative then
2309               Val := In_Vec (J) * Base + In_Vec (J + 1);
2310
2311               if Val <= Max_Direct then
2312                  return Uint (Int (Uint_Direct_Bias) + Val);
2313               end if;
2314            end if;
2315
2316            --  The value is outside the direct representation range and must
2317            --  therefore be stored in the table. Expand the table to contain
2318            --  the count and digits. The index of the new table entry will be
2319            --  returned as the result.
2320
2321            Uints.Append ((Length => Size, Loc => Udigits.Last + 1));
2322
2323            if Negative then
2324               Val := -In_Vec (J);
2325            else
2326               Val := +In_Vec (J);
2327            end if;
2328
2329            Udigits.Append (Val);
2330
2331            for K in 2 .. Size loop
2332               Udigits.Append (In_Vec (J + K - 1));
2333            end loop;
2334
2335            return Uints.Last;
2336         end if;
2337      end loop;
2338
2339      --  Dropped through loop only if vector contained all zeros
2340
2341      return Uint_0;
2342   end Vector_To_Uint;
2343
2344end Uintp;
2345