annotate gcc/ada/uintp.adb @ 131:84e7813d76e9

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