1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2018, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
33 with Output
; use Output
;
35 with Tree_IO
; use Tree_IO
;
37 package body Urealp
is
39 Ureal_First_Entry
: constant Ureal
:= Ureal
'Succ (No_Ureal
);
40 -- First subscript allocated in Ureal table (note that we can't just
41 -- add 1 to No_Ureal, since "+" means something different for Ureals).
43 type Ureal_Entry
is record
45 -- Numerator (always non-negative)
48 -- Denominator (always non-zero, always positive if base is zero)
51 -- Base value. If Rbase is zero, then the value is simply Num / Den.
52 -- If Rbase is non-zero, then the value is Num / (Rbase ** Den)
55 -- Flag set if value is negative
58 -- The following representation clause ensures that the above record
59 -- has no holes. We do this so that when instances of this record are
60 -- written by Tree_Gen, we do not write uninitialized values to the file.
62 for Ureal_Entry
use record
63 Num
at 0 range 0 .. 31;
64 Den
at 4 range 0 .. 31;
65 Rbase
at 8 range 0 .. 31;
66 Negative
at 12 range 0 .. 31;
69 for Ureal_Entry
'Size use 16 * 8;
70 -- This ensures that we did not leave out any fields
72 package Ureals
is new Table
.Table
(
73 Table_Component_Type
=> Ureal_Entry
,
74 Table_Index_Type
=> Ureal
'Base,
75 Table_Low_Bound
=> Ureal_First_Entry
,
76 Table_Initial
=> Alloc
.Ureals_Initial
,
77 Table_Increment
=> Alloc
.Ureals_Increment
,
78 Table_Name
=> "Ureals");
80 -- The following universal reals are the values returned by the constant
81 -- functions. They are initialized by the initialization procedure.
98 Num_Ureal_Constants
: constant := 10;
99 -- This is used for an assertion check in Tree_Read and Tree_Write to
100 -- help remember to add values to these routines when we add to the list.
102 Normalized_Real
: Ureal
:= No_Ureal
;
103 -- Used to memoize Norm_Num and Norm_Den, if either of these functions
104 -- is called, this value is set and Normalized_Entry contains the result
105 -- of the normalization. On subsequent calls, this is used to avoid the
106 -- call to Normalize if it has already been made.
108 Normalized_Entry
: Ureal_Entry
;
109 -- Entry built by most recent call to Normalize
111 -----------------------
112 -- Local Subprograms --
113 -----------------------
115 function Decimal_Exponent_Hi
(V
: Ureal
) return Int
;
116 -- Returns an estimate of the exponent of Val represented as a normalized
117 -- decimal number (non-zero digit before decimal point), The estimate is
118 -- either correct, or high, but never low. The accuracy of the estimate
119 -- affects only the efficiency of the comparison routines.
121 function Decimal_Exponent_Lo
(V
: Ureal
) return Int
;
122 -- Returns an estimate of the exponent of Val represented as a normalized
123 -- decimal number (non-zero digit before decimal point), The estimate is
124 -- either correct, or low, but never high. The accuracy of the estimate
125 -- affects only the efficiency of the comparison routines.
127 function Equivalent_Decimal_Exponent
(U
: Ureal_Entry
) return Int
;
128 -- U is a Ureal entry for which the base value is non-zero, the value
129 -- returned is the equivalent decimal exponent value, i.e. the value of
130 -- Den, adjusted as though the base were base 10. The value is rounded
131 -- toward zero (truncated), and so its value can be off by one.
133 function Is_Integer
(Num
, Den
: Uint
) return Boolean;
134 -- Return true if the real quotient of Num / Den is an integer value
136 function Normalize
(Val
: Ureal_Entry
) return Ureal_Entry
;
137 -- Normalizes the Ureal_Entry by reducing it to lowest terms (with a base
140 function Same
(U1
, U2
: Ureal
) return Boolean;
141 pragma Inline
(Same
);
142 -- Determines if U1 and U2 are the same Ureal. Note that we cannot use
143 -- the equals operator for this test, since that tests for equality, not
146 function Store_Ureal
(Val
: Ureal_Entry
) return Ureal
;
147 -- This store a new entry in the universal reals table and return its index
150 function Store_Ureal_Normalized
(Val
: Ureal_Entry
) return Ureal
;
151 pragma Inline
(Store_Ureal_Normalized
);
152 -- Like Store_Ureal, but normalizes its operand first
154 -------------------------
155 -- Decimal_Exponent_Hi --
156 -------------------------
158 function Decimal_Exponent_Hi
(V
: Ureal
) return Int
is
159 Val
: constant Ureal_Entry
:= Ureals
.Table
(V
);
162 -- Zero always returns zero
164 if UR_Is_Zero
(V
) then
167 -- For numbers in rational form, get the maximum number of digits in the
168 -- numerator and the minimum number of digits in the denominator, and
169 -- subtract. For example:
171 -- 1000 / 99 = 1.010E+1
172 -- 9999 / 10 = 9.999E+2
174 -- This estimate may of course be high, but that is acceptable
176 elsif Val
.Rbase
= 0 then
177 return UI_Decimal_Digits_Hi
(Val
.Num
) -
178 UI_Decimal_Digits_Lo
(Val
.Den
);
180 -- For based numbers, just subtract the decimal exponent from the
181 -- high estimate of the number of digits in the numerator and add
182 -- one to accommodate possible round off errors for non-decimal
183 -- bases. For example:
185 -- 1_500_000 / 10**4 = 1.50E-2
187 else -- Val.Rbase /= 0
188 return UI_Decimal_Digits_Hi
(Val
.Num
) -
189 Equivalent_Decimal_Exponent
(Val
) + 1;
191 end Decimal_Exponent_Hi
;
193 -------------------------
194 -- Decimal_Exponent_Lo --
195 -------------------------
197 function Decimal_Exponent_Lo
(V
: Ureal
) return Int
is
198 Val
: constant Ureal_Entry
:= Ureals
.Table
(V
);
201 -- Zero always returns zero
203 if UR_Is_Zero
(V
) then
206 -- For numbers in rational form, get min digits in numerator, max digits
207 -- in denominator, and subtract and subtract one more for possible loss
208 -- during the division. For example:
210 -- 1000 / 99 = 1.010E+1
211 -- 9999 / 10 = 9.999E+2
213 -- This estimate may of course be low, but that is acceptable
215 elsif Val
.Rbase
= 0 then
216 return UI_Decimal_Digits_Lo
(Val
.Num
) -
217 UI_Decimal_Digits_Hi
(Val
.Den
) - 1;
219 -- For based numbers, just subtract the decimal exponent from the
220 -- low estimate of the number of digits in the numerator and subtract
221 -- one to accommodate possible round off errors for non-decimal
222 -- bases. For example:
224 -- 1_500_000 / 10**4 = 1.50E-2
226 else -- Val.Rbase /= 0
227 return UI_Decimal_Digits_Lo
(Val
.Num
) -
228 Equivalent_Decimal_Exponent
(Val
) - 1;
230 end Decimal_Exponent_Lo
;
236 function Denominator
(Real
: Ureal
) return Uint
is
238 return Ureals
.Table
(Real
).Den
;
241 ---------------------------------
242 -- Equivalent_Decimal_Exponent --
243 ---------------------------------
245 function Equivalent_Decimal_Exponent
(U
: Ureal_Entry
) return Int
is
252 -- The following table is a table of logs to the base 10. All values
253 -- have at least 15 digits of precision, and do not exceed the true
254 -- value. To avoid the use of floating point, and as a result potential
255 -- target dependency, each entry is represented as a fraction of two
258 Logs
: constant array (Nat
range 1 .. 16) of Ratio
:=
259 (1 => (Num
=> 0, Den
=> 1), -- 0
260 2 => (Num
=> 15_392_313
, Den
=> 51_132_157
), -- 0.301029995663981
261 3 => (Num
=> 731_111_920
, Den
=> 1532_339_867
), -- 0.477121254719662
262 4 => (Num
=> 30_784_626
, Den
=> 51_132_157
), -- 0.602059991327962
263 5 => (Num
=> 111_488_153
, Den
=> 159_503_487
), -- 0.698970004336018
264 6 => (Num
=> 84_253_929
, Den
=> 108_274_489
), -- 0.778151250383643
265 7 => (Num
=> 35_275_468
, Den
=> 41_741_273
), -- 0.845098040014256
266 8 => (Num
=> 46_176_939
, Den
=> 51_132_157
), -- 0.903089986991943
267 9 => (Num
=> 417_620_173
, Den
=> 437_645_744
), -- 0.954242509439324
268 10 => (Num
=> 1, Den
=> 1), -- 1.000000000000000
269 11 => (Num
=> 136_507_510
, Den
=> 131_081_687
), -- 1.041392685158225
270 12 => (Num
=> 26_797_783
, Den
=> 24_831_587
), -- 1.079181246047624
271 13 => (Num
=> 73_333_297
, Den
=> 65_832_160
), -- 1.113943352306836
272 14 => (Num
=> 102_941_258
, Den
=> 89_816_543
), -- 1.146128035678238
273 15 => (Num
=> 53_385_559
, Den
=> 45_392_361
), -- 1.176091259055681
274 16 => (Num
=> 78_897_839
, Den
=> 65_523_237
)); -- 1.204119982655924
276 function Scale
(X
: Int
; R
: Ratio
) return Int
;
277 -- Compute the value of X scaled by R
283 function Scale
(X
: Int
; R
: Ratio
) return Int
is
284 type Wide_Int
is range -2**63 .. 2**63 - 1;
287 return Int
(Wide_Int
(X
) * Wide_Int
(R
.Num
) / Wide_Int
(R
.Den
));
291 pragma Assert
(U
.Rbase
/= 0);
292 return Scale
(UI_To_Int
(U
.Den
), Logs
(U
.Rbase
));
293 end Equivalent_Decimal_Exponent
;
299 procedure Initialize
is
302 UR_0
:= UR_From_Components
(Uint_0
, Uint_1
, 0, False);
303 UR_M_0
:= UR_From_Components
(Uint_0
, Uint_1
, 0, True);
304 UR_Half
:= UR_From_Components
(Uint_1
, Uint_1
, 2, False);
305 UR_Tenth
:= UR_From_Components
(Uint_1
, Uint_1
, 10, False);
306 UR_1
:= UR_From_Components
(Uint_1
, Uint_1
, 0, False);
307 UR_2
:= UR_From_Components
(Uint_1
, Uint_Minus_1
, 2, False);
308 UR_10
:= UR_From_Components
(Uint_1
, Uint_Minus_1
, 10, False);
309 UR_10_36
:= UR_From_Components
(Uint_1
, Uint_Minus_36
, 10, False);
310 UR_M_10_36
:= UR_From_Components
(Uint_1
, Uint_Minus_36
, 10, True);
311 UR_100
:= UR_From_Components
(Uint_1
, Uint_Minus_2
, 10, False);
312 UR_2_128
:= UR_From_Components
(Uint_1
, Uint_Minus_128
, 2, False);
313 UR_2_M_128
:= UR_From_Components
(Uint_1
, Uint_128
, 2, False);
314 UR_2_80
:= UR_From_Components
(Uint_1
, Uint_Minus_80
, 2, False);
315 UR_2_M_80
:= UR_From_Components
(Uint_1
, Uint_80
, 2, False);
322 function Is_Integer
(Num
, Den
: Uint
) return Boolean is
324 return (Num
/ Den
) * Den
= Num
;
331 function Mark
return Save_Mark
is
333 return Save_Mark
(Ureals
.Last
);
340 function Norm_Den
(Real
: Ureal
) return Uint
is
342 if not Same
(Real
, Normalized_Real
) then
343 Normalized_Real
:= Real
;
344 Normalized_Entry
:= Normalize
(Ureals
.Table
(Real
));
347 return Normalized_Entry
.Den
;
354 function Norm_Num
(Real
: Ureal
) return Uint
is
356 if not Same
(Real
, Normalized_Real
) then
357 Normalized_Real
:= Real
;
358 Normalized_Entry
:= Normalize
(Ureals
.Table
(Real
));
361 return Normalized_Entry
.Num
;
368 function Normalize
(Val
: Ureal_Entry
) return Ureal_Entry
is
374 M
: constant Uintp
.Save_Mark
:= Uintp
.Mark
;
377 -- Start by setting J to the greatest of the absolute values of the
378 -- numerator and the denominator (taking into account the base value),
379 -- and K to the lesser of the two absolute values. The gcd of Num and
380 -- Den is the gcd of J and K.
382 if Val
.Rbase
= 0 then
386 elsif Val
.Den
< 0 then
387 J
:= Val
.Num
* Val
.Rbase
** (-Val
.Den
);
392 K
:= Val
.Rbase
** Val
.Den
;
407 Uintp
.Release_And_Save
(M
, Num
, Den
);
409 -- Divide numerator and denominator by gcd and return result
414 Negative
=> Val
.Negative
);
421 function Numerator
(Real
: Ureal
) return Uint
is
423 return Ureals
.Table
(Real
).Num
;
430 procedure pr
(Real
: Ureal
) is
440 function Rbase
(Real
: Ureal
) return Nat
is
442 return Ureals
.Table
(Real
).Rbase
;
449 procedure Release
(M
: Save_Mark
) is
451 Ureals
.Set_Last
(Ureal
(M
));
458 function Same
(U1
, U2
: Ureal
) return Boolean is
460 return Int
(U1
) = Int
(U2
);
467 function Store_Ureal
(Val
: Ureal_Entry
) return Ureal
is
471 -- Normalize representation of signed values
474 Ureals
.Table
(Ureals
.Last
).Negative
:= True;
475 Ureals
.Table
(Ureals
.Last
).Num
:= -Val
.Num
;
481 ----------------------------
482 -- Store_Ureal_Normalized --
483 ----------------------------
485 function Store_Ureal_Normalized
(Val
: Ureal_Entry
) return Ureal
is
487 return Store_Ureal
(Normalize
(Val
));
488 end Store_Ureal_Normalized
;
494 procedure Tree_Read
is
496 pragma Assert
(Num_Ureal_Constants
= 10);
499 Tree_Read_Int
(Int
(UR_0
));
500 Tree_Read_Int
(Int
(UR_M_0
));
501 Tree_Read_Int
(Int
(UR_Tenth
));
502 Tree_Read_Int
(Int
(UR_Half
));
503 Tree_Read_Int
(Int
(UR_1
));
504 Tree_Read_Int
(Int
(UR_2
));
505 Tree_Read_Int
(Int
(UR_10
));
506 Tree_Read_Int
(Int
(UR_100
));
507 Tree_Read_Int
(Int
(UR_2_128
));
508 Tree_Read_Int
(Int
(UR_2_M_128
));
510 -- Clear the normalization cache
512 Normalized_Real
:= No_Ureal
;
519 procedure Tree_Write
is
521 pragma Assert
(Num_Ureal_Constants
= 10);
524 Tree_Write_Int
(Int
(UR_0
));
525 Tree_Write_Int
(Int
(UR_M_0
));
526 Tree_Write_Int
(Int
(UR_Tenth
));
527 Tree_Write_Int
(Int
(UR_Half
));
528 Tree_Write_Int
(Int
(UR_1
));
529 Tree_Write_Int
(Int
(UR_2
));
530 Tree_Write_Int
(Int
(UR_10
));
531 Tree_Write_Int
(Int
(UR_100
));
532 Tree_Write_Int
(Int
(UR_2_128
));
533 Tree_Write_Int
(Int
(UR_2_M_128
));
540 function UR_Abs
(Real
: Ureal
) return Ureal
is
541 Val
: constant Ureal_Entry
:= Ureals
.Table
(Real
);
555 function UR_Add
(Left
: Uint
; Right
: Ureal
) return Ureal
is
557 return UR_From_Uint
(Left
) + Right
;
560 function UR_Add
(Left
: Ureal
; Right
: Uint
) return Ureal
is
562 return Left
+ UR_From_Uint
(Right
);
565 function UR_Add
(Left
: Ureal
; Right
: Ureal
) return Ureal
is
566 Lval
: Ureal_Entry
:= Ureals
.Table
(Left
);
567 Rval
: Ureal_Entry
:= Ureals
.Table
(Right
);
571 -- Note, in the temporary Ureal_Entry values used in this procedure,
572 -- we store the sign as the sign of the numerator (i.e. xxx.Num may
573 -- be negative, even though in stored entries this can never be so)
575 if Lval
.Rbase
/= 0 and then Lval
.Rbase
= Rval
.Rbase
then
577 Opd_Min
, Opd_Max
: Ureal_Entry
;
578 Exp_Min
, Exp_Max
: Uint
;
581 if Lval
.Negative
then
582 Lval
.Num
:= (-Lval
.Num
);
585 if Rval
.Negative
then
586 Rval
.Num
:= (-Rval
.Num
);
589 if Lval
.Den
< Rval
.Den
then
602 Opd_Min
.Num
* Lval
.Rbase
** (Exp_Max
- Exp_Min
) + Opd_Max
.Num
;
609 Negative
=> Lval
.Negative
));
616 Negative
=> (Num
< 0)));
622 Ln
: Ureal_Entry
:= Normalize
(Lval
);
623 Rn
: Ureal_Entry
:= Normalize
(Rval
);
634 Num
:= (Ln
.Num
* Rn
.Den
) + (Rn
.Num
* Ln
.Den
);
641 Negative
=> Lval
.Negative
));
644 return Store_Ureal_Normalized
646 Den
=> Ln
.Den
* Rn
.Den
,
648 Negative
=> (Num
< 0)));
658 function UR_Ceiling
(Real
: Ureal
) return Uint
is
659 Val
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
662 return UI_Negate
(Val
.Num
/ Val
.Den
);
664 return (Val
.Num
+ Val
.Den
- 1) / Val
.Den
;
672 function UR_Div
(Left
: Uint
; Right
: Ureal
) return Ureal
is
674 return UR_From_Uint
(Left
) / Right
;
677 function UR_Div
(Left
: Ureal
; Right
: Uint
) return Ureal
is
679 return Left
/ UR_From_Uint
(Right
);
682 function UR_Div
(Left
, Right
: Ureal
) return Ureal
is
683 Lval
: constant Ureal_Entry
:= Ureals
.Table
(Left
);
684 Rval
: constant Ureal_Entry
:= Ureals
.Table
(Right
);
685 Rneg
: constant Boolean := Rval
.Negative
xor Lval
.Negative
;
688 pragma Assert
(Rval
.Num
/= Uint_0
);
690 if Lval
.Rbase
= 0 then
691 if Rval
.Rbase
= 0 then
692 return Store_Ureal_Normalized
693 ((Num
=> Lval
.Num
* Rval
.Den
,
694 Den
=> Lval
.Den
* Rval
.Num
,
698 elsif Is_Integer
(Lval
.Num
, Rval
.Num
* Lval
.Den
) then
700 ((Num
=> Lval
.Num
/ (Rval
.Num
* Lval
.Den
),
705 elsif Rval
.Den
< 0 then
706 return Store_Ureal_Normalized
708 Den
=> Rval
.Rbase
** (-Rval
.Den
) *
715 return Store_Ureal_Normalized
716 ((Num
=> Lval
.Num
* Rval
.Rbase
** Rval
.Den
,
717 Den
=> Rval
.Num
* Lval
.Den
,
722 elsif Is_Integer
(Lval
.Num
, Rval
.Num
) then
723 if Rval
.Rbase
= Lval
.Rbase
then
725 ((Num
=> Lval
.Num
/ Rval
.Num
,
726 Den
=> Lval
.Den
- Rval
.Den
,
730 elsif Rval
.Rbase
= 0 then
732 ((Num
=> (Lval
.Num
/ Rval
.Num
) * Rval
.Den
,
737 elsif Rval
.Den
< 0 then
743 Num
:= (Lval
.Num
/ Rval
.Num
) * (Lval
.Rbase
** (-Lval
.Den
));
744 Den
:= Rval
.Rbase
** (-Rval
.Den
);
746 Num
:= Lval
.Num
/ Rval
.Num
;
747 Den
:= (Lval
.Rbase
** Lval
.Den
) *
748 (Rval
.Rbase
** (-Rval
.Den
));
760 ((Num
=> (Lval
.Num
/ Rval
.Num
) *
761 (Rval
.Rbase
** Rval
.Den
),
773 Num
:= Lval
.Num
* (Lval
.Rbase
** (-Lval
.Den
));
777 Den
:= Rval
.Num
* (Lval
.Rbase
** Lval
.Den
);
780 if Rval
.Rbase
/= 0 then
782 Den
:= Den
* (Rval
.Rbase
** (-Rval
.Den
));
784 Num
:= Num
* (Rval
.Rbase
** Rval
.Den
);
788 Num
:= Num
* Rval
.Den
;
791 return Store_Ureal_Normalized
804 function UR_Eq
(Left
, Right
: Ureal
) return Boolean is
806 return not UR_Ne
(Left
, Right
);
809 ---------------------
810 -- UR_Exponentiate --
811 ---------------------
813 function UR_Exponentiate
(Real
: Ureal
; N
: Uint
) return Ureal
is
814 X
: constant Uint
:= abs N
;
821 -- If base is negative, then the resulting sign depends on whether
822 -- the exponent is even or odd (even => positive, odd = negative)
824 if UR_Is_Negative
(Real
) then
825 Neg
:= (N
mod 2) /= 0;
826 Bas
:= UR_Negate
(Real
);
832 Val
:= Ureals
.Table
(Bas
);
834 -- If the base is a small integer, then we can return the result in
835 -- exponential form, which can save a lot of time for junk exponents.
837 IBas
:= UR_Trunc
(Bas
);
840 and then UR_From_Uint
(IBas
) = Bas
845 Rbase
=> UI_To_Int
(UR_Trunc
(Bas
)),
848 -- If the exponent is negative then we raise the numerator and the
849 -- denominator (after normalization) to the absolute value of the
850 -- exponent and we return the reciprocal. An assert error will happen
851 -- if the numerator is zero.
854 pragma Assert
(Val
.Num
/= 0);
855 Val
:= Normalize
(Val
);
858 ((Num
=> Val
.Den
** X
,
863 -- If positive, we distinguish the case when the base is not zero, in
864 -- which case the new denominator is just the product of the old one
865 -- with the exponent,
868 if Val
.Rbase
/= 0 then
871 ((Num
=> Val
.Num
** X
,
876 -- And when the base is zero, in which case we exponentiate
877 -- the old denominator.
881 ((Num
=> Val
.Num
** X
,
893 function UR_Floor
(Real
: Ureal
) return Uint
is
894 Val
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
897 return UI_Negate
((Val
.Num
+ Val
.Den
- 1) / Val
.Den
);
899 return Val
.Num
/ Val
.Den
;
903 ------------------------
904 -- UR_From_Components --
905 ------------------------
907 function UR_From_Components
911 Negative
: Boolean := False)
919 Negative
=> Negative
));
920 end UR_From_Components
;
926 function UR_From_Uint
(UI
: Uint
) return Ureal
is
928 return UR_From_Components
929 (abs UI
, Uint_1
, Negative
=> (UI
< 0));
936 function UR_Ge
(Left
, Right
: Ureal
) return Boolean is
938 return not (Left
< Right
);
945 function UR_Gt
(Left
, Right
: Ureal
) return Boolean is
947 return (Right
< Left
);
954 function UR_Is_Negative
(Real
: Ureal
) return Boolean is
956 return Ureals
.Table
(Real
).Negative
;
963 function UR_Is_Positive
(Real
: Ureal
) return Boolean is
965 return not Ureals
.Table
(Real
).Negative
966 and then Ureals
.Table
(Real
).Num
/= 0;
973 function UR_Is_Zero
(Real
: Ureal
) return Boolean is
975 return Ureals
.Table
(Real
).Num
= 0;
982 function UR_Le
(Left
, Right
: Ureal
) return Boolean is
984 return not (Right
< Left
);
991 function UR_Lt
(Left
, Right
: Ureal
) return Boolean is
993 -- An operand is not less than itself
995 if Same
(Left
, Right
) then
998 -- Deal with zero cases
1000 elsif UR_Is_Zero
(Left
) then
1001 return UR_Is_Positive
(Right
);
1003 elsif UR_Is_Zero
(Right
) then
1004 return Ureals
.Table
(Left
).Negative
;
1006 -- Different signs are decisive (note we dealt with zero cases)
1008 elsif Ureals
.Table
(Left
).Negative
1009 and then not Ureals
.Table
(Right
).Negative
1013 elsif not Ureals
.Table
(Left
).Negative
1014 and then Ureals
.Table
(Right
).Negative
1018 -- Signs are same, do rapid check based on worst case estimates of
1019 -- decimal exponent, which will often be decisive. Precise test
1020 -- depends on whether operands are positive or negative.
1022 elsif Decimal_Exponent_Hi
(Left
) < Decimal_Exponent_Lo
(Right
) then
1023 return UR_Is_Positive
(Left
);
1025 elsif Decimal_Exponent_Lo
(Left
) > Decimal_Exponent_Hi
(Right
) then
1026 return UR_Is_Negative
(Left
);
1028 -- If we fall through, full gruesome test is required. This happens
1029 -- if the numbers are close together, or in some weird (/=10) base.
1033 Imrk
: constant Uintp
.Save_Mark
:= Mark
;
1034 Rmrk
: constant Urealp
.Save_Mark
:= Mark
;
1040 Lval
:= Ureals
.Table
(Left
);
1041 Rval
:= Ureals
.Table
(Right
);
1043 -- An optimization. If both numbers are based, then subtract
1044 -- common value of base to avoid unnecessarily giant numbers
1046 if Lval
.Rbase
= Rval
.Rbase
and then Lval
.Rbase
/= 0 then
1047 if Lval
.Den
< Rval
.Den
then
1048 Rval
.Den
:= Rval
.Den
- Lval
.Den
;
1051 Lval
.Den
:= Lval
.Den
- Rval
.Den
;
1056 Lval
:= Normalize
(Lval
);
1057 Rval
:= Normalize
(Rval
);
1059 if Lval
.Negative
then
1060 Result
:= (Lval
.Num
* Rval
.Den
) > (Rval
.Num
* Lval
.Den
);
1062 Result
:= (Lval
.Num
* Rval
.Den
) < (Rval
.Num
* Lval
.Den
);
1076 function UR_Max
(Left
, Right
: Ureal
) return Ureal
is
1078 if Left
>= Right
then
1089 function UR_Min
(Left
, Right
: Ureal
) return Ureal
is
1091 if Left
<= Right
then
1102 function UR_Mul
(Left
: Uint
; Right
: Ureal
) return Ureal
is
1104 return UR_From_Uint
(Left
) * Right
;
1107 function UR_Mul
(Left
: Ureal
; Right
: Uint
) return Ureal
is
1109 return Left
* UR_From_Uint
(Right
);
1112 function UR_Mul
(Left
, Right
: Ureal
) return Ureal
is
1113 Lval
: constant Ureal_Entry
:= Ureals
.Table
(Left
);
1114 Rval
: constant Ureal_Entry
:= Ureals
.Table
(Right
);
1115 Num
: Uint
:= Lval
.Num
* Rval
.Num
;
1117 Rneg
: constant Boolean := Lval
.Negative
xor Rval
.Negative
;
1120 if Lval
.Rbase
= 0 then
1121 if Rval
.Rbase
= 0 then
1122 return Store_Ureal_Normalized
1124 Den
=> Lval
.Den
* Rval
.Den
,
1128 elsif Is_Integer
(Num
, Lval
.Den
) then
1130 ((Num
=> Num
/ Lval
.Den
,
1132 Rbase
=> Rval
.Rbase
,
1135 elsif Rval
.Den
< 0 then
1136 return Store_Ureal_Normalized
1137 ((Num
=> Num
* (Rval
.Rbase
** (-Rval
.Den
)),
1143 return Store_Ureal_Normalized
1145 Den
=> Lval
.Den
* (Rval
.Rbase
** Rval
.Den
),
1150 elsif Lval
.Rbase
= Rval
.Rbase
then
1153 Den
=> Lval
.Den
+ Rval
.Den
,
1154 Rbase
=> Lval
.Rbase
,
1157 elsif Rval
.Rbase
= 0 then
1158 if Is_Integer
(Num
, Rval
.Den
) then
1160 ((Num
=> Num
/ Rval
.Den
,
1162 Rbase
=> Lval
.Rbase
,
1165 elsif Lval
.Den
< 0 then
1166 return Store_Ureal_Normalized
1167 ((Num
=> Num
* (Lval
.Rbase
** (-Lval
.Den
)),
1173 return Store_Ureal_Normalized
1175 Den
=> Rval
.Den
* (Lval
.Rbase
** Lval
.Den
),
1183 if Lval
.Den
< 0 then
1184 Num
:= Num
* (Lval
.Rbase
** (-Lval
.Den
));
1186 Den
:= Den
* (Lval
.Rbase
** Lval
.Den
);
1189 if Rval
.Den
< 0 then
1190 Num
:= Num
* (Rval
.Rbase
** (-Rval
.Den
));
1192 Den
:= Den
* (Rval
.Rbase
** Rval
.Den
);
1195 return Store_Ureal_Normalized
1207 function UR_Ne
(Left
, Right
: Ureal
) return Boolean is
1209 -- Quick processing for case of identical Ureal values (note that
1210 -- this also deals with comparing two No_Ureal values).
1212 if Same
(Left
, Right
) then
1215 -- Deal with case of one or other operand is No_Ureal, but not both
1217 elsif Same
(Left
, No_Ureal
) or else Same
(Right
, No_Ureal
) then
1220 -- Do quick check based on number of decimal digits
1222 elsif Decimal_Exponent_Hi
(Left
) < Decimal_Exponent_Lo
(Right
) or else
1223 Decimal_Exponent_Lo
(Left
) > Decimal_Exponent_Hi
(Right
)
1227 -- Otherwise full comparison is required
1231 Imrk
: constant Uintp
.Save_Mark
:= Mark
;
1232 Rmrk
: constant Urealp
.Save_Mark
:= Mark
;
1233 Lval
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Left
));
1234 Rval
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Right
));
1238 if UR_Is_Zero
(Left
) then
1239 return not UR_Is_Zero
(Right
);
1241 elsif UR_Is_Zero
(Right
) then
1242 return not UR_Is_Zero
(Left
);
1244 -- Both operands are non-zero
1248 Rval
.Negative
/= Lval
.Negative
1249 or else Rval
.Num
/= Lval
.Num
1250 or else Rval
.Den
/= Lval
.Den
;
1263 function UR_Negate
(Real
: Ureal
) return Ureal
is
1266 ((Num
=> Ureals
.Table
(Real
).Num
,
1267 Den
=> Ureals
.Table
(Real
).Den
,
1268 Rbase
=> Ureals
.Table
(Real
).Rbase
,
1269 Negative
=> not Ureals
.Table
(Real
).Negative
));
1276 function UR_Sub
(Left
: Uint
; Right
: Ureal
) return Ureal
is
1278 return UR_From_Uint
(Left
) + UR_Negate
(Right
);
1281 function UR_Sub
(Left
: Ureal
; Right
: Uint
) return Ureal
is
1283 return Left
+ UR_From_Uint
(-Right
);
1286 function UR_Sub
(Left
, Right
: Ureal
) return Ureal
is
1288 return Left
+ UR_Negate
(Right
);
1295 function UR_To_Uint
(Real
: Ureal
) return Uint
is
1296 Val
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
1300 Res
:= (Val
.Num
+ (Val
.Den
/ 2)) / Val
.Den
;
1302 if Val
.Negative
then
1303 return UI_Negate
(Res
);
1313 function UR_Trunc
(Real
: Ureal
) return Uint
is
1314 Val
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
1316 if Val
.Negative
then
1317 return -(Val
.Num
/ Val
.Den
);
1319 return Val
.Num
/ Val
.Den
;
1327 procedure UR_Write
(Real
: Ureal
; Brackets
: Boolean := False) is
1328 Val
: constant Ureal_Entry
:= Ureals
.Table
(Real
);
1332 -- If value is negative, we precede the constant by a minus sign
1334 if Val
.Negative
then
1343 -- For constants with a denominator of zero, the value is simply the
1344 -- numerator value, since we are dividing by base**0, which is 1.
1346 elsif Val
.Den
= 0 then
1347 UI_Write
(Val
.Num
, Decimal
);
1350 -- Small powers of 2 get written in decimal fixed-point format
1353 and then Val
.Den
<= 3
1354 and then Val
.Den
>= -16
1357 T
:= Val
.Num
* (10 / 2);
1358 UI_Write
(T
/ 10, Decimal
);
1360 UI_Write
(T
mod 10, Decimal
);
1362 elsif Val
.Den
= 2 then
1363 T
:= Val
.Num
* (100 / 4);
1364 UI_Write
(T
/ 100, Decimal
);
1366 UI_Write
(T
mod 100 / 10, Decimal
);
1368 if T
mod 10 /= 0 then
1369 UI_Write
(T
mod 10, Decimal
);
1372 elsif Val
.Den
= 3 then
1373 T
:= Val
.Num
* (1000 / 8);
1374 UI_Write
(T
/ 1000, Decimal
);
1376 UI_Write
(T
mod 1000 / 100, Decimal
);
1378 if T
mod 100 /= 0 then
1379 UI_Write
(T
mod 100 / 10, Decimal
);
1381 if T
mod 10 /= 0 then
1382 UI_Write
(T
mod 10, Decimal
);
1387 UI_Write
(Val
.Num
* (Uint_2
** (-Val
.Den
)), Decimal
);
1391 -- Constants in base 10 or 16 can be written in normal Ada literal
1392 -- style, as long as they fit in the UI_Image_Buffer. Using hexadecimal
1393 -- notation, 4 bytes are required for the 16# # part, and every fifth
1394 -- character is an underscore. So, a buffer of size N has room for
1395 -- ((N - 4) - (N - 4) / 5) * 4 bits,
1397 -- N * 16 / 5 - 12 bits.
1399 elsif (Val
.Rbase
= 10 or else Val
.Rbase
= 16)
1400 and then Num_Bits
(Val
.Num
) < UI_Image_Buffer
'Length * 16 / 5 - 12
1402 pragma Assert
(Val
.Den
/= 0);
1404 -- Use fixed-point format for small scaling values
1406 if (Val
.Rbase
= 10 and then Val
.Den
< 0 and then Val
.Den
> -3)
1407 or else (Val
.Rbase
= 16 and then Val
.Den
= -1)
1409 UI_Write
(Val
.Num
* Val
.Rbase
**(-Val
.Den
), Decimal
);
1412 -- Write hexadecimal constants in exponential notation with a zero
1413 -- unit digit. This matches the Ada canonical form for floating point
1414 -- numbers, and also ensures that the underscores end up in the
1417 elsif Val
.Rbase
= 16 then
1418 UI_Image
(Val
.Num
, Hex
);
1419 pragma Assert
(Val
.Rbase
= 16);
1421 Write_Str
("16#0.");
1422 Write_Str
(UI_Image_Buffer
(4 .. UI_Image_Length
));
1424 -- For exponent, exclude 16# # and underscores from length
1426 UI_Image_Length
:= UI_Image_Length
- 4;
1427 UI_Image_Length
:= UI_Image_Length
- UI_Image_Length
/ 5;
1430 UI_Write
(Int
(UI_Image_Length
) - Val
.Den
, Decimal
);
1432 elsif Val
.Den
= 1 then
1433 UI_Write
(Val
.Num
/ 10, Decimal
);
1435 UI_Write
(Val
.Num
mod 10, Decimal
);
1437 elsif Val
.Den
= 2 then
1438 UI_Write
(Val
.Num
/ 100, Decimal
);
1440 UI_Write
(Val
.Num
/ 10 mod 10, Decimal
);
1441 UI_Write
(Val
.Num
mod 10, Decimal
);
1443 -- Else use decimal exponential format
1446 -- Write decimal constants with a non-zero unit digit. This
1447 -- matches usual scientific notation.
1449 UI_Image
(Val
.Num
, Decimal
);
1450 Write_Char
(UI_Image_Buffer
(1));
1453 if UI_Image_Length
= 1 then
1456 Write_Str
(UI_Image_Buffer
(2 .. UI_Image_Length
));
1460 UI_Write
(Int
(UI_Image_Length
- 1) - Val
.Den
, Decimal
);
1463 -- Constants in a base other than 10 can still be easily written in
1464 -- normal Ada literal style if the numerator is one.
1466 elsif Val
.Rbase
/= 0 and then Val
.Num
= 1 then
1467 Write_Int
(Val
.Rbase
);
1468 Write_Str
("#1.0#E");
1469 UI_Write
(-Val
.Den
);
1471 -- Other constants with a base other than 10 are written using one of
1472 -- the following forms, depending on the sign of the number and the
1473 -- sign of the exponent (= minus denominator value). See that we are
1474 -- replacing the division by a multiplication (updating accordingly the
1475 -- sign of the exponent) to generate an expression whose computation
1476 -- does not cause a division by 0 when base**exponent is very small.
1478 -- numerator.0*base**exponent
1479 -- numerator.0*base**-exponent
1481 -- And of course an exponent of 0 can be omitted.
1483 elsif Val
.Rbase
/= 0 then
1488 UI_Write
(Val
.Num
, Decimal
);
1491 if Val
.Den
/= 0 then
1493 Write_Int
(Val
.Rbase
);
1496 if Val
.Den
<= 0 then
1497 UI_Write
(-Val
.Den
, Decimal
);
1500 UI_Write
(Val
.Den
, Decimal
);
1509 -- Rationals where numerator is divisible by denominator can be output
1510 -- as literals after we do the division. This includes the common case
1511 -- where the denominator is 1.
1513 elsif Val
.Num
mod Val
.Den
= 0 then
1514 UI_Write
(Val
.Num
/ Val
.Den
, Decimal
);
1517 -- Other non-based (rational) constants are written in num/den style
1524 UI_Write
(Val
.Num
, Decimal
);
1526 UI_Write
(Val
.Den
, Decimal
);
1539 function Ureal_0
return Ureal
is
1548 function Ureal_1
return Ureal
is
1557 function Ureal_2
return Ureal
is
1566 function Ureal_10
return Ureal
is
1575 function Ureal_100
return Ureal
is
1584 function Ureal_10_36
return Ureal
is
1593 function Ureal_2_80
return Ureal
is
1602 function Ureal_2_128
return Ureal
is
1611 function Ureal_2_M_80
return Ureal
is
1620 function Ureal_2_M_128
return Ureal
is
1629 function Ureal_Half
return Ureal
is
1638 function Ureal_M_0
return Ureal
is
1647 function Ureal_M_10_36
return Ureal
is
1656 function Ureal_Tenth
return Ureal
is