OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [ada/] [uintp.adb] - Blame information for rev 826

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.