File : uintp.adb


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