1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2024, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
27 with Output
; use Output
;
30 package body Urealp
is
32 Ureal_First_Entry
: constant Ureal
:= Ureal
'Succ (No_Ureal
);
33 -- First subscript allocated in Ureal table (note that we can't just
34 -- add 1 to No_Ureal, since "+" means something different for Ureals).
36 type Ureal_Entry
is record
38 -- Numerator (always non-negative)
41 -- Denominator (always non-zero, always positive if base is zero)
44 -- Base value. If Rbase is zero, then the value is simply Num / Den.
45 -- If Rbase is non-zero, then the value is Num / (Rbase ** Den)
48 -- Flag set if value is negative
51 -- The following representation clause ensures that the above record
52 -- has no holes. We do this so that when instances of this record are
53 -- written, we do not write uninitialized values to the file.
55 for Ureal_Entry
use record
56 Num
at 0 range 0 .. 31;
57 Den
at 4 range 0 .. 31;
58 Rbase
at 8 range 0 .. 31;
59 Negative
at 12 range 0 .. 31;
62 for Ureal_Entry
'Size use 16 * 8;
63 -- This ensures that we did not leave out any fields
65 package Ureals
is new Table
.Table
(
66 Table_Component_Type
=> Ureal_Entry
,
67 Table_Index_Type
=> Ureal
'Base,
68 Table_Low_Bound
=> Ureal_First_Entry
,
69 Table_Initial
=> Alloc
.Ureals_Initial
,
70 Table_Increment
=> Alloc
.Ureals_Increment
,
71 Table_Name
=> "Ureals");
73 -- The following universal reals are the values returned by the constant
74 -- functions. They are initialized by the initialization procedure.
99 Normalized_Real
: Ureal
:= No_Ureal
;
100 -- Used to memoize Norm_Num and Norm_Den, if either of these functions
101 -- is called, this value is set and Normalized_Entry contains the result
102 -- of the normalization. On subsequent calls, this is used to avoid the
103 -- call to Normalize if it has already been made.
105 Normalized_Entry
: Ureal_Entry
;
106 -- Entry built by most recent call to Normalize
108 -----------------------
109 -- Local Subprograms --
110 -----------------------
112 function Decimal_Exponent_Hi
(V
: Ureal
) return Int
;
113 -- Returns an estimate of the exponent of Val represented as a normalized
114 -- decimal number (non-zero digit before decimal point), the estimate is
115 -- either correct, or high, but never low. The accuracy of the estimate
116 -- affects only the efficiency of the comparison routines.
118 function Decimal_Exponent_Lo
(V
: Ureal
) return Int
;
119 -- Returns an estimate of the exponent of Val represented as a normalized
120 -- decimal number (non-zero digit before decimal point), the estimate is
121 -- either correct, or low, but never high. The accuracy of the estimate
122 -- affects only the efficiency of the comparison routines.
124 function Equivalent_Decimal_Exponent
(U
: Ureal_Entry
) return Int
;
125 -- U is a Ureal entry for which the base value is non-zero, the value
126 -- returned is the equivalent decimal exponent value, i.e. the value of
127 -- Den, adjusted as though the base were base 10. The value is rounded
128 -- toward zero (truncated), and so its value can be off by one.
130 function Is_Integer
(Num
, Den
: Uint
) return Boolean;
131 -- Return true if the real quotient of Num / Den is an integer value
133 function Normalize
(Val
: Ureal_Entry
) return Ureal_Entry
;
134 -- Normalizes the Ureal_Entry by reducing it to lowest terms (with a base
137 function Same
(U1
, U2
: Ureal
) return Boolean;
138 pragma Inline
(Same
);
139 -- Determines if U1 and U2 are the same Ureal. Note that we cannot use
140 -- the equals operator for this test, since that tests for equality, not
143 function Store_Ureal
(Val
: Ureal_Entry
) return Ureal
;
144 -- This store a new entry in the universal reals table and return its index
147 function Store_Ureal_Normalized
(Val
: Ureal_Entry
) return Ureal
;
148 pragma Inline
(Store_Ureal_Normalized
);
149 -- Like Store_Ureal, but normalizes its operand first
151 -------------------------
152 -- Decimal_Exponent_Hi --
153 -------------------------
155 function Decimal_Exponent_Hi
(V
: Ureal
) return Int
is
156 Val
: constant Ureal_Entry
:= Ureals
.Table
(V
);
159 -- Zero always returns zero
161 if UR_Is_Zero
(V
) then
164 -- For numbers in rational form, get the maximum number of digits in the
165 -- numerator and the minimum number of digits in the denominator, and
166 -- subtract. For example:
168 -- 1000 / 99 = 1.010E+1
169 -- 9999 / 10 = 9.999E+2
171 -- This estimate may of course be high, but that is acceptable
173 elsif Val
.Rbase
= 0 then
174 return UI_Decimal_Digits_Hi
(Val
.Num
) -
175 UI_Decimal_Digits_Lo
(Val
.Den
);
177 -- For based numbers, get the maximum number of digits in the numerator
178 -- minus one and the either exact or floor value of the decimal exponent
179 -- of the denominator, and subtract. For example:
181 -- 321 / 10**3 = 3.21E-1
182 -- 435 / 5**7 = 5.57E-3
189 if Val
.Rbase
= 10 then
190 E
:= UI_To_Int
(Val
.Den
);
193 E
:= Equivalent_Decimal_Exponent
(Val
);
199 return UI_Decimal_Digits_Hi
(Val
.Num
) - 1 - E
;
202 end Decimal_Exponent_Hi
;
204 -------------------------
205 -- Decimal_Exponent_Lo --
206 -------------------------
208 function Decimal_Exponent_Lo
(V
: Ureal
) return Int
is
209 Val
: constant Ureal_Entry
:= Ureals
.Table
(V
);
212 -- Zero always returns zero
214 if UR_Is_Zero
(V
) then
217 -- For numbers in rational form, get min digits in numerator, max digits
218 -- in denominator, and subtract and subtract one more for possible loss
219 -- during the division. For example:
221 -- 1000 / 99 = 1.010E+1
222 -- 9999 / 10 = 9.999E+2
224 -- This estimate may of course be low, but that is acceptable
226 elsif Val
.Rbase
= 0 then
227 return UI_Decimal_Digits_Lo
(Val
.Num
) -
228 UI_Decimal_Digits_Hi
(Val
.Den
) - 1;
230 -- For based numbers, get the minimum number of digits in the numerator
231 -- minus one and the either exact or ceil value of the decimal exponent
232 -- of the denominator, and subtract. For example:
234 -- 321 / 10**3 = 3.21E-1
235 -- 435 / 5**7 = 5.57E-3
242 if Val
.Rbase
= 10 then
243 E
:= UI_To_Int
(Val
.Den
);
246 E
:= Equivalent_Decimal_Exponent
(Val
);
252 return UI_Decimal_Digits_Lo
(Val
.Num
) - 1 - E
;
255 end Decimal_Exponent_Lo
;
261 function Denominator
(Real
: Ureal
) return Uint
is
263 return Ureals
.Table
(Real
).Den
;
266 ---------------------------------
267 -- Equivalent_Decimal_Exponent --
268 ---------------------------------
270 function Equivalent_Decimal_Exponent
(U
: Ureal_Entry
) return Int
is
277 -- The following table is a table of logs to the base 10. All values
278 -- have at least 15 digits of precision, and do not exceed the true
279 -- value. To avoid the use of floating point, and as a result potential
280 -- target dependency, each entry is represented as a fraction of two
283 Logs
: constant array (Nat
range 1 .. 16) of Ratio
:=
284 (1 => (Num
=> 0, Den
=> 1), -- 0
285 2 => (Num
=> 15_392_313
, Den
=> 51_132_157
), -- 0.301029995663981
286 3 => (Num
=> 731_111_920
, Den
=> 1532_339_867
), -- 0.477121254719662
287 4 => (Num
=> 30_784_626
, Den
=> 51_132_157
), -- 0.602059991327962
288 5 => (Num
=> 111_488_153
, Den
=> 159_503_487
), -- 0.698970004336018
289 6 => (Num
=> 84_253_929
, Den
=> 108_274_489
), -- 0.778151250383643
290 7 => (Num
=> 35_275_468
, Den
=> 41_741_273
), -- 0.845098040014256
291 8 => (Num
=> 46_176_939
, Den
=> 51_132_157
), -- 0.903089986991943
292 9 => (Num
=> 417_620_173
, Den
=> 437_645_744
), -- 0.954242509439324
293 10 => (Num
=> 1, Den
=> 1), -- 1.000000000000000
294 11 => (Num
=> 136_507_510
, Den
=> 131_081_687
), -- 1.041392685158225
295 12 => (Num
=> 26_797_783
, Den
=> 24_831_587
), -- 1.079181246047624
296 13 => (Num
=> 73_333_297
, Den
=> 65_832_160
), -- 1.113943352306836
297 14 => (Num
=> 102_941_258
, Den
=> 89_816_543
), -- 1.146128035678238
298 15 => (Num
=> 53_385_559
, Den
=> 45_392_361
), -- 1.176091259055681
299 16 => (Num
=> 78_897_839
, Den
=> 65_523_237
)); -- 1.204119982655924
301 function Scale
(X
: Uint
; R
: Ratio
) return Int
;
302 -- Compute the value of X scaled by R
308 function Scale
(X
: Uint
; R
: Ratio
) return Int
is
310 return UI_To_Int
(X
* R
.Num
/ R
.Den
);
314 pragma Assert
(U
.Rbase
/= 0);
315 return Scale
(U
.Den
, Logs
(U
.Rbase
));
316 end Equivalent_Decimal_Exponent
;
322 procedure Initialize
is
325 UR_0
:= UR_From_Components
(Uint_0
, Uint_1
, 0, False);
326 UR_M_0
:= UR_From_Components
(Uint_0
, Uint_1
, 0, True);
327 UR_Half
:= UR_From_Components
(Uint_1
, Uint_1
, 2, False);
328 UR_Tenth
:= UR_From_Components
(Uint_1
, Uint_1
, 10, False);
329 UR_1
:= UR_From_Components
(Uint_1
, Uint_1
, 0, False);
330 UR_2
:= UR_From_Components
(Uint_1
, Uint_Minus_1
, 2, False);
331 UR_10
:= UR_From_Components
(Uint_1
, Uint_Minus_1
, 10, False);
332 UR_2_10_18
:= UR_From_Components
(Uint_2
, Uint_Minus_18
, 10, False);
333 UR_9_10_36
:= UR_From_Components
(Uint_9
, Uint_Minus_36
, 10, False);
334 UR_10_76
:= UR_From_Components
(Uint_1
, Uint_Minus_76
, 10, False);
335 UR_M_2_10_18
:= UR_From_Components
(Uint_2
, Uint_Minus_18
, 10, True);
336 UR_M_9_10_36
:= UR_From_Components
(Uint_9
, Uint_Minus_36
, 10, True);
337 UR_M_10_76
:= UR_From_Components
(Uint_1
, Uint_Minus_76
, 10, True);
338 UR_100
:= UR_From_Components
(Uint_1
, Uint_Minus_2
, 10, False);
339 UR_2_127
:= UR_From_Components
(Uint_1
, Uint_Minus_127
, 2, False);
340 UR_2_M_127
:= UR_From_Components
(Uint_1
, Uint_127
, 2, False);
341 UR_2_128
:= UR_From_Components
(Uint_1
, Uint_Minus_128
, 2, False);
342 UR_2_M_128
:= UR_From_Components
(Uint_1
, Uint_128
, 2, False);
343 UR_2_31
:= UR_From_Components
(Uint_1
, Uint_Minus_31
, 2, False);
344 UR_2_63
:= UR_From_Components
(Uint_1
, Uint_Minus_63
, 2, False);
345 UR_2_80
:= UR_From_Components
(Uint_1
, Uint_Minus_80
, 2, False);
346 UR_2_M_80
:= UR_From_Components
(Uint_1
, Uint_80
, 2, False);
353 function Is_Integer
(Num
, Den
: Uint
) return Boolean is
355 return (Num
/ Den
) * Den
= Num
;
362 function Mark
return Save_Mark
is
364 return Save_Mark
(Ureals
.Last
);
371 function Norm_Den
(Real
: Ureal
) return Uint
is
373 if not Same
(Real
, Normalized_Real
) then
374 Normalized_Real
:= Real
;
375 Normalized_Entry
:= Normalize
(Ureals
.Table
(Real
));
378 return Normalized_Entry
.Den
;
385 function Norm_Num
(Real
: Ureal
) return Uint
is
387 if not Same
(Real
, Normalized_Real
) then
388 Normalized_Real
:= Real
;
389 Normalized_Entry
:= Normalize
(Ureals
.Table
(Real
));
392 return Normalized_Entry
.Num
;
399 function Normalize
(Val
: Ureal_Entry
) return Ureal_Entry
is
405 M
: constant Uintp
.Save_Mark
:= Mark
;
408 -- Start by setting J to the greatest of the absolute values of the
409 -- numerator and the denominator (taking into account the base value),
410 -- and K to the lesser of the two absolute values. The gcd of Num and
411 -- Den is the gcd of J and K.
413 if Val
.Rbase
= 0 then
417 elsif Val
.Den
< 0 then
418 J
:= Val
.Num
* Val
.Rbase
** (-Val
.Den
);
423 K
:= Val
.Rbase
** Val
.Den
;
438 Uintp
.Release_And_Save
(M
, Num
, Den
);
440 -- Divide numerator and denominator by gcd and return result
445 Negative
=> Val
.Negative
);
452 function Numerator
(Real
: Ureal
) return Uint
is
454 return Ureals
.Table
(Real
).Num
;
461 procedure pr
(Real
: Ureal
) is
471 function Rbase
(Real
: Ureal
) return Nat
is
473 return Ureals
.Table
(Real
).Rbase
;
480 procedure Release
(M
: Save_Mark
) is
482 Ureals
.Set_Last
(Ureal
(M
));
489 function Same
(U1
, U2
: Ureal
) return Boolean is
491 return Int
(U1
) = Int
(U2
);
498 function Store_Ureal
(Val
: Ureal_Entry
) return Ureal
is
502 -- Normalize representation of signed values
505 Ureals
.Table
(Ureals
.Last
).Negative
:= True;
506 Ureals
.Table
(Ureals
.Last
).Num
:= -Val
.Num
;
512 ----------------------------
513 -- Store_Ureal_Normalized --
514 ----------------------------
516 function Store_Ureal_Normalized
(Val
: Ureal_Entry
) return Ureal
is
518 return Store_Ureal
(Normalize
(Val
));
519 end Store_Ureal_Normalized
;
525 function UR_Abs
(Real
: Ureal
) return Ureal
is
526 Val
: constant Ureal_Entry
:= Ureals
.Table
(Real
);
540 function UR_Add
(Left
: Uint
; Right
: Ureal
) return Ureal
is
542 return UR_From_Uint
(Left
) + Right
;
545 function UR_Add
(Left
: Ureal
; Right
: Uint
) return Ureal
is
547 return Left
+ UR_From_Uint
(Right
);
550 function UR_Add
(Left
: Ureal
; Right
: Ureal
) return Ureal
is
551 Lval
: Ureal_Entry
:= Ureals
.Table
(Left
);
552 Rval
: Ureal_Entry
:= Ureals
.Table
(Right
);
556 pragma Annotate
(CodePeer
, Modified
, Lval
);
557 pragma Annotate
(CodePeer
, Modified
, Rval
);
559 -- Note, in the temporary Ureal_Entry values used in this procedure,
560 -- we store the sign as the sign of the numerator (i.e. xxx.Num may
561 -- be negative, even though in stored entries this can never be so)
563 if Lval
.Rbase
/= 0 and then Lval
.Rbase
= Rval
.Rbase
then
565 Opd_Min
, Opd_Max
: Ureal_Entry
;
566 Exp_Min
, Exp_Max
: Uint
;
569 if Lval
.Negative
then
570 Lval
.Num
:= (-Lval
.Num
);
573 if Rval
.Negative
then
574 Rval
.Num
:= (-Rval
.Num
);
577 if Lval
.Den
< Rval
.Den
then
590 Opd_Min
.Num
* Lval
.Rbase
** (Exp_Max
- Exp_Min
) + Opd_Max
.Num
;
597 Negative
=> Lval
.Negative
));
604 Negative
=> (Num
< 0)));
610 Ln
: Ureal_Entry
:= Normalize
(Lval
);
611 Rn
: Ureal_Entry
:= Normalize
(Rval
);
622 Num
:= (Ln
.Num
* Rn
.Den
) + (Rn
.Num
* Ln
.Den
);
629 Negative
=> Lval
.Negative
));
632 return Store_Ureal_Normalized
634 Den
=> Ln
.Den
* Rn
.Den
,
636 Negative
=> (Num
< 0)));
646 function UR_Ceiling
(Real
: Ureal
) return Uint
is
647 Val
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
650 return UI_Negate
(Val
.Num
/ Val
.Den
);
652 return (Val
.Num
+ Val
.Den
- 1) / Val
.Den
;
660 function UR_Div
(Left
: Uint
; Right
: Ureal
) return Ureal
is
662 return UR_From_Uint
(Left
) / Right
;
665 function UR_Div
(Left
: Ureal
; Right
: Uint
) return Ureal
is
667 return Left
/ UR_From_Uint
(Right
);
670 function UR_Div
(Left
, Right
: Ureal
) return Ureal
is
671 Lval
: constant Ureal_Entry
:= Ureals
.Table
(Left
);
672 Rval
: constant Ureal_Entry
:= Ureals
.Table
(Right
);
673 Rneg
: constant Boolean := Rval
.Negative
xor Lval
.Negative
;
676 pragma Annotate
(CodePeer
, Modified
, Lval
);
677 pragma Annotate
(CodePeer
, Modified
, Rval
);
678 pragma Assert
(Rval
.Num
/= Uint_0
);
680 if Lval
.Rbase
= 0 then
681 if Rval
.Rbase
= 0 then
682 return Store_Ureal_Normalized
683 ((Num
=> Lval
.Num
* Rval
.Den
,
684 Den
=> Lval
.Den
* Rval
.Num
,
688 elsif Is_Integer
(Lval
.Num
, Rval
.Num
* Lval
.Den
) then
690 ((Num
=> Lval
.Num
/ (Rval
.Num
* Lval
.Den
),
695 elsif Rval
.Den
< 0 then
696 return Store_Ureal_Normalized
698 Den
=> Rval
.Rbase
** (-Rval
.Den
) *
705 return Store_Ureal_Normalized
706 ((Num
=> Lval
.Num
* Rval
.Rbase
** Rval
.Den
,
707 Den
=> Rval
.Num
* Lval
.Den
,
712 elsif Is_Integer
(Lval
.Num
, Rval
.Num
) then
713 if Rval
.Rbase
= Lval
.Rbase
then
715 ((Num
=> Lval
.Num
/ Rval
.Num
,
716 Den
=> Lval
.Den
- Rval
.Den
,
720 elsif Rval
.Rbase
= 0 then
722 ((Num
=> (Lval
.Num
/ Rval
.Num
) * Rval
.Den
,
727 elsif Rval
.Den
< 0 then
733 Num
:= (Lval
.Num
/ Rval
.Num
) * (Lval
.Rbase
** (-Lval
.Den
));
734 Den
:= Rval
.Rbase
** (-Rval
.Den
);
736 Num
:= Lval
.Num
/ Rval
.Num
;
737 Den
:= (Lval
.Rbase
** Lval
.Den
) *
738 (Rval
.Rbase
** (-Rval
.Den
));
750 ((Num
=> (Lval
.Num
/ Rval
.Num
) *
751 (Rval
.Rbase
** Rval
.Den
),
763 Num
:= Lval
.Num
* (Lval
.Rbase
** (-Lval
.Den
));
767 Den
:= Rval
.Num
* (Lval
.Rbase
** Lval
.Den
);
770 if Rval
.Rbase
/= 0 then
772 Den
:= Den
* (Rval
.Rbase
** (-Rval
.Den
));
774 Num
:= Num
* (Rval
.Rbase
** Rval
.Den
);
778 Num
:= Num
* Rval
.Den
;
781 return Store_Ureal_Normalized
794 function UR_Eq
(Left
, Right
: Ureal
) return Boolean is
796 return not UR_Ne
(Left
, Right
);
799 ---------------------
800 -- UR_Exponentiate --
801 ---------------------
803 function UR_Exponentiate
(Real
: Ureal
; N
: Uint
) return Ureal
is
804 X
: constant Uint
:= abs N
;
811 -- If base is negative, then the resulting sign depends on whether
812 -- the exponent is even or odd (even => positive, odd = negative)
814 if UR_Is_Negative
(Real
) then
815 Neg
:= (N
mod 2) /= 0;
816 Bas
:= UR_Negate
(Real
);
822 Val
:= Ureals
.Table
(Bas
);
824 -- If the base is a small integer, then we can return the result in
825 -- exponential form, which can save a lot of time for junk exponents.
827 IBas
:= UR_Trunc
(Bas
);
830 and then UR_From_Uint
(IBas
) = Bas
835 Rbase
=> UI_To_Int
(UR_Trunc
(Bas
)),
838 -- If the exponent is negative then we raise the numerator and the
839 -- denominator (after normalization) to the absolute value of the
840 -- exponent and we return the reciprocal. An assert error will happen
841 -- if the numerator is zero.
844 pragma Assert
(Val
.Num
/= 0);
845 Val
:= Normalize
(Val
);
848 ((Num
=> Val
.Den
** X
,
853 -- If positive, we distinguish the case when the base is not zero, in
854 -- which case the new denominator is just the product of the old one
855 -- with the exponent,
858 if Val
.Rbase
/= 0 then
861 ((Num
=> Val
.Num
** X
,
866 -- And when the base is zero, in which case we exponentiate
867 -- the old denominator.
871 ((Num
=> Val
.Num
** X
,
883 function UR_Floor
(Real
: Ureal
) return Uint
is
884 Val
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
887 return UI_Negate
((Val
.Num
+ Val
.Den
- 1) / Val
.Den
);
889 return Val
.Num
/ Val
.Den
;
893 ------------------------
894 -- UR_From_Components --
895 ------------------------
897 function UR_From_Components
901 Negative
: Boolean := False)
909 Negative
=> Negative
));
910 end UR_From_Components
;
916 function UR_From_Uint
(UI
: Uint
) return Ureal
is
918 return UR_From_Components
919 (abs UI
, Uint_1
, Negative
=> (UI
< 0));
926 function UR_Ge
(Left
, Right
: Ureal
) return Boolean is
928 return not (Left
< Right
);
935 function UR_Gt
(Left
, Right
: Ureal
) return Boolean is
937 return (Right
< Left
);
944 function UR_Is_Negative
(Real
: Ureal
) return Boolean is
946 return Ureals
.Table
(Real
).Negative
;
953 function UR_Is_Positive
(Real
: Ureal
) return Boolean is
955 return not Ureals
.Table
(Real
).Negative
956 and then Ureals
.Table
(Real
).Num
/= 0;
963 function UR_Is_Zero
(Real
: Ureal
) return Boolean is
965 return Ureals
.Table
(Real
).Num
= 0;
972 function UR_Le
(Left
, Right
: Ureal
) return Boolean is
974 return not (Right
< Left
);
981 function UR_Lt
(Left
, Right
: Ureal
) return Boolean is
983 -- An operand is not less than itself
985 if Same
(Left
, Right
) then
988 -- Deal with zero cases
990 elsif UR_Is_Zero
(Left
) then
991 return UR_Is_Positive
(Right
);
993 elsif UR_Is_Zero
(Right
) then
994 return Ureals
.Table
(Left
).Negative
;
996 -- Different signs are decisive (note we dealt with zero cases)
998 elsif Ureals
.Table
(Left
).Negative
999 and then not Ureals
.Table
(Right
).Negative
1003 elsif not Ureals
.Table
(Left
).Negative
1004 and then Ureals
.Table
(Right
).Negative
1008 -- Signs are same, do rapid check based on worst case estimates of
1009 -- decimal exponent, which will often be decisive. Precise test
1010 -- depends on whether operands are positive or negative.
1012 elsif Decimal_Exponent_Hi
(Left
) < Decimal_Exponent_Lo
(Right
) then
1013 return UR_Is_Positive
(Left
);
1015 elsif Decimal_Exponent_Lo
(Left
) > Decimal_Exponent_Hi
(Right
) then
1016 return UR_Is_Negative
(Left
);
1018 -- If we fall through, full gruesome test is required. This happens
1019 -- if the numbers are close together, or in some weird (/=10) base.
1023 Imrk
: constant Uintp
.Save_Mark
:= Mark
;
1024 Rmrk
: constant Urealp
.Save_Mark
:= Mark
;
1030 Lval
:= Ureals
.Table
(Left
);
1031 Rval
:= Ureals
.Table
(Right
);
1033 -- An optimization. If both numbers are based, then subtract
1034 -- common value of base to avoid unnecessarily giant numbers
1036 if Lval
.Rbase
= Rval
.Rbase
and then Lval
.Rbase
/= 0 then
1037 if Lval
.Den
< Rval
.Den
then
1038 Rval
.Den
:= Rval
.Den
- Lval
.Den
;
1041 Lval
.Den
:= Lval
.Den
- Rval
.Den
;
1046 Lval
:= Normalize
(Lval
);
1047 Rval
:= Normalize
(Rval
);
1049 if Lval
.Negative
then
1050 Result
:= (Lval
.Num
* Rval
.Den
) > (Rval
.Num
* Lval
.Den
);
1052 Result
:= (Lval
.Num
* Rval
.Den
) < (Rval
.Num
* Lval
.Den
);
1066 function UR_Max
(Left
, Right
: Ureal
) return Ureal
is
1068 if Left
>= Right
then
1079 function UR_Min
(Left
, Right
: Ureal
) return Ureal
is
1081 if Left
<= Right
then
1092 function UR_Mul
(Left
: Uint
; Right
: Ureal
) return Ureal
is
1094 return UR_From_Uint
(Left
) * Right
;
1097 function UR_Mul
(Left
: Ureal
; Right
: Uint
) return Ureal
is
1099 return Left
* UR_From_Uint
(Right
);
1102 function UR_Mul
(Left
, Right
: Ureal
) return Ureal
is
1103 Lval
: constant Ureal_Entry
:= Ureals
.Table
(Left
);
1104 Rval
: constant Ureal_Entry
:= Ureals
.Table
(Right
);
1105 Num
: Uint
:= Lval
.Num
* Rval
.Num
;
1107 Rneg
: constant Boolean := Lval
.Negative
xor Rval
.Negative
;
1110 if Lval
.Rbase
= 0 then
1111 if Rval
.Rbase
= 0 then
1112 return Store_Ureal_Normalized
1114 Den
=> Lval
.Den
* Rval
.Den
,
1118 elsif Is_Integer
(Num
, Lval
.Den
) then
1120 ((Num
=> Num
/ Lval
.Den
,
1122 Rbase
=> Rval
.Rbase
,
1125 elsif Rval
.Den
< 0 then
1126 return Store_Ureal_Normalized
1127 ((Num
=> Num
* (Rval
.Rbase
** (-Rval
.Den
)),
1133 return Store_Ureal_Normalized
1135 Den
=> Lval
.Den
* (Rval
.Rbase
** Rval
.Den
),
1140 elsif Lval
.Rbase
= Rval
.Rbase
then
1143 Den
=> Lval
.Den
+ Rval
.Den
,
1144 Rbase
=> Lval
.Rbase
,
1147 elsif Rval
.Rbase
= 0 then
1148 if Is_Integer
(Num
, Rval
.Den
) then
1150 ((Num
=> Num
/ Rval
.Den
,
1152 Rbase
=> Lval
.Rbase
,
1155 elsif Lval
.Den
< 0 then
1156 return Store_Ureal_Normalized
1157 ((Num
=> Num
* (Lval
.Rbase
** (-Lval
.Den
)),
1163 return Store_Ureal_Normalized
1165 Den
=> Rval
.Den
* (Lval
.Rbase
** Lval
.Den
),
1173 if Lval
.Den
< 0 then
1174 Num
:= Num
* (Lval
.Rbase
** (-Lval
.Den
));
1176 Den
:= Den
* (Lval
.Rbase
** Lval
.Den
);
1179 if Rval
.Den
< 0 then
1180 Num
:= Num
* (Rval
.Rbase
** (-Rval
.Den
));
1182 Den
:= Den
* (Rval
.Rbase
** Rval
.Den
);
1185 return Store_Ureal_Normalized
1197 function UR_Ne
(Left
, Right
: Ureal
) return Boolean is
1199 -- Quick processing for case of identical Ureal values (note that
1200 -- this also deals with comparing two No_Ureal values).
1202 if Same
(Left
, Right
) then
1205 -- Deal with case of one or other operand is No_Ureal, but not both
1207 elsif Same
(Left
, No_Ureal
) or else Same
(Right
, No_Ureal
) then
1210 -- Do quick check based on number of decimal digits
1212 elsif Decimal_Exponent_Hi
(Left
) < Decimal_Exponent_Lo
(Right
) or else
1213 Decimal_Exponent_Lo
(Left
) > Decimal_Exponent_Hi
(Right
)
1217 -- Otherwise full comparison is required
1221 Imrk
: constant Uintp
.Save_Mark
:= Mark
;
1222 Rmrk
: constant Urealp
.Save_Mark
:= Mark
;
1223 Lval
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Left
));
1224 Rval
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Right
));
1228 if UR_Is_Zero
(Left
) then
1229 return not UR_Is_Zero
(Right
);
1231 elsif UR_Is_Zero
(Right
) then
1232 return not UR_Is_Zero
(Left
);
1234 -- Both operands are non-zero
1238 Rval
.Negative
/= Lval
.Negative
1239 or else Rval
.Num
/= Lval
.Num
1240 or else Rval
.Den
/= Lval
.Den
;
1253 function UR_Negate
(Real
: Ureal
) return Ureal
is
1256 ((Num
=> Ureals
.Table
(Real
).Num
,
1257 Den
=> Ureals
.Table
(Real
).Den
,
1258 Rbase
=> Ureals
.Table
(Real
).Rbase
,
1259 Negative
=> not Ureals
.Table
(Real
).Negative
));
1266 function UR_Sub
(Left
: Uint
; Right
: Ureal
) return Ureal
is
1268 return UR_From_Uint
(Left
) + UR_Negate
(Right
);
1271 function UR_Sub
(Left
: Ureal
; Right
: Uint
) return Ureal
is
1273 return Left
+ UR_From_Uint
(-Right
);
1276 function UR_Sub
(Left
, Right
: Ureal
) return Ureal
is
1278 return Left
+ UR_Negate
(Right
);
1285 function UR_To_Uint
(Real
: Ureal
) return Uint
is
1286 Val
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
1290 Res
:= (Val
.Num
+ (Val
.Den
/ 2)) / Val
.Den
;
1292 if Val
.Negative
then
1293 return UI_Negate
(Res
);
1303 function UR_Trunc
(Real
: Ureal
) return Uint
is
1304 Val
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
1306 if Val
.Negative
then
1307 return -(Val
.Num
/ Val
.Den
);
1309 return Val
.Num
/ Val
.Den
;
1317 procedure UR_Write
(Real
: Ureal
; Brackets
: Boolean := False) is
1318 Val
: constant Ureal_Entry
:= Ureals
.Table
(Real
);
1322 -- If value is negative, we precede the constant by a minus sign
1324 if Val
.Negative
then
1333 -- For constants with a denominator of zero, the value is simply the
1334 -- numerator value, since we are dividing by base**0, which is 1.
1336 elsif Val
.Den
= 0 then
1337 UI_Write
(Val
.Num
, Decimal
);
1340 -- Small powers of 2 get written in decimal fixed-point format
1343 and then Val
.Den
<= 3
1344 and then Val
.Den
>= -16
1347 T
:= Val
.Num
* (10 / 2);
1348 UI_Write
(T
/ 10, Decimal
);
1350 UI_Write
(T
mod 10, Decimal
);
1352 elsif Val
.Den
= 2 then
1353 T
:= Val
.Num
* (100 / 4);
1354 UI_Write
(T
/ 100, Decimal
);
1356 UI_Write
(T
mod 100 / 10, Decimal
);
1358 if T
mod 10 /= 0 then
1359 UI_Write
(T
mod 10, Decimal
);
1362 elsif Val
.Den
= 3 then
1363 T
:= Val
.Num
* (1000 / 8);
1364 UI_Write
(T
/ 1000, Decimal
);
1366 UI_Write
(T
mod 1000 / 100, Decimal
);
1368 if T
mod 100 /= 0 then
1369 UI_Write
(T
mod 100 / 10, Decimal
);
1371 if T
mod 10 /= 0 then
1372 UI_Write
(T
mod 10, Decimal
);
1377 UI_Write
(Val
.Num
* (Uint_2
** (-Val
.Den
)), Decimal
);
1381 -- Constants in base 10 or 16 can be written in normal Ada literal
1382 -- style, as long as they fit in the UI_Image_Buffer. Using hexadecimal
1383 -- notation, 4 bytes are required for the 16# # part, and every fifth
1384 -- character is an underscore. So, a buffer of size N has room for
1385 -- ((N - 4) - (N - 4) / 5) * 4 bits,
1387 -- N * 16 / 5 - 12 bits.
1389 elsif (Val
.Rbase
= 10 or else Val
.Rbase
= 16)
1390 and then Num_Bits
(Val
.Num
) < UI_Image_Buffer
'Length * 16 / 5 - 12
1392 pragma Assert
(Val
.Den
/= 0);
1394 -- Use fixed-point format for small scaling values
1396 if (Val
.Rbase
= 10 and then Val
.Den
< 0 and then Val
.Den
> -3)
1397 or else (Val
.Rbase
= 16 and then Val
.Den
= -1)
1399 UI_Write
(Val
.Num
* Val
.Rbase
**(-Val
.Den
), Decimal
);
1402 -- Write hexadecimal constants in exponential notation with a zero
1403 -- unit digit. This matches the Ada canonical form for floating point
1404 -- numbers, and also ensures that the underscores end up in the
1407 elsif Val
.Rbase
= 16 then
1408 UI_Image
(Val
.Num
, Hex
);
1409 pragma Assert
(Val
.Rbase
= 16);
1411 Write_Str
("16#0.");
1412 Write_Str
(UI_Image_Buffer
(4 .. UI_Image_Length
));
1414 -- For exponent, exclude 16# # and underscores from length
1416 UI_Image_Length
:= UI_Image_Length
- 4;
1417 UI_Image_Length
:= UI_Image_Length
- UI_Image_Length
/ 5;
1420 UI_Write
(Int
(UI_Image_Length
) - Val
.Den
, Decimal
);
1422 elsif Val
.Den
= 1 then
1423 UI_Write
(Val
.Num
/ 10, Decimal
);
1425 UI_Write
(Val
.Num
mod 10, Decimal
);
1427 elsif Val
.Den
= 2 then
1428 UI_Write
(Val
.Num
/ 100, Decimal
);
1430 UI_Write
(Val
.Num
/ 10 mod 10, Decimal
);
1431 UI_Write
(Val
.Num
mod 10, Decimal
);
1433 -- Else use decimal exponential format
1436 -- Write decimal constants with a non-zero unit digit. This
1437 -- matches usual scientific notation.
1439 UI_Image
(Val
.Num
, Decimal
);
1440 Write_Char
(UI_Image_Buffer
(1));
1443 if UI_Image_Length
= 1 then
1446 Write_Str
(UI_Image_Buffer
(2 .. UI_Image_Length
));
1450 UI_Write
(Int
(UI_Image_Length
- 1) - Val
.Den
, Decimal
);
1453 -- Other constants with a base other than 10 are written using one of
1454 -- the following forms, depending on the sign of the number and the
1455 -- sign of the exponent (= minus denominator value). See that we are
1456 -- replacing the division by a multiplication (updating accordingly the
1457 -- sign of the exponent) to generate an expression whose computation
1458 -- does not cause a division by 0 when base**exponent is very small.
1460 -- numerator.0*base**exponent
1461 -- numerator.0*base**-exponent
1463 -- And of course an exponent of 0 can be omitted.
1465 elsif Val
.Rbase
/= 0 then
1470 UI_Write
(Val
.Num
, Decimal
);
1473 if Val
.Den
/= 0 then
1475 Write_Int
(Val
.Rbase
);
1478 if Val
.Den
<= 0 then
1479 UI_Write
(-Val
.Den
, Decimal
);
1482 UI_Write
(Val
.Den
, Decimal
);
1491 -- Rationals where numerator is divisible by denominator can be output
1492 -- as literals after we do the division. This includes the common case
1493 -- where the denominator is 1.
1495 elsif Val
.Num
mod Val
.Den
= 0 then
1496 UI_Write
(Val
.Num
/ Val
.Den
, Decimal
);
1499 -- Other non-based (rational) constants are written in num/den style
1506 UI_Write
(Val
.Num
, Decimal
);
1508 UI_Write
(Val
.Den
, Decimal
);
1517 ----------------------
1518 -- UR_Write_To_JSON --
1519 ----------------------
1521 -- We defer to the implementation of UR_Write for values that are naturally
1522 -- written in a JSON compatible format and write a fraction for the others.
1524 procedure UR_Write_To_JSON
(Real
: Ureal
) is
1525 Val
: constant Ureal_Entry
:= Ureals
.Table
(Real
);
1535 -- For constants with a denominator of zero, the value is simply the
1536 -- numerator value, since we are dividing by base**0, which is 1.
1538 elsif Val
.Den
= 0 then
1541 -- Small powers of 2 get written in decimal fixed-point format
1544 and then Val
.Den
<= 3
1545 and then Val
.Den
>= -16
1549 -- Constants in base 10 can be written in normal Ada literal style
1551 elsif Val
.Rbase
= 10 then
1554 -- Rationals where numerator is divisible by denominator can be output
1555 -- as literals after we do the division. This includes the common case
1556 -- where the denominator is 1.
1558 elsif Val
.Rbase
= 0 and then Val
.Num
mod Val
.Den
= 0 then
1561 -- Other non-based (rational) constants are written in num/den style
1564 Write_Str
("{ ""code"": ""/"", ""operands"": [ ");
1565 if Val
.Negative
then
1568 UI_Write
(Val
.Num
, Decimal
);
1570 UI_Write
(Val
.Den
, Decimal
);
1571 Write_Str
(".0 ] }");
1576 end UR_Write_To_JSON
;
1582 function Ureal_0
return Ureal
is
1591 function Ureal_1
return Ureal
is
1600 function Ureal_2
return Ureal
is
1609 function Ureal_10
return Ureal
is
1618 function Ureal_100
return Ureal
is
1627 function Ureal_2_10_18
return Ureal
is
1636 function Ureal_9_10_36
return Ureal
is
1645 function Ureal_10_76
return Ureal
is
1654 function Ureal_2_31
return Ureal
is
1663 function Ureal_2_63
return Ureal
is
1672 function Ureal_2_80
return Ureal
is
1681 function Ureal_2_127
return Ureal
is
1690 function Ureal_2_128
return Ureal
is
1699 function Ureal_2_M_80
return Ureal
is
1708 function Ureal_2_M_127
return Ureal
is
1717 function Ureal_2_M_128
return Ureal
is
1726 function Ureal_Half
return Ureal
is
1735 function Ureal_M_0
return Ureal
is
1740 ---------------------
1741 -- Ureal_M_2_10_18 --
1742 ---------------------
1744 function Ureal_M_2_10_18
return Ureal
is
1746 return UR_M_2_10_18
;
1747 end Ureal_M_2_10_18
;
1749 ---------------------
1750 -- Ureal_M_9_10_36 --
1751 ---------------------
1753 function Ureal_M_9_10_36
return Ureal
is
1755 return UR_M_9_10_36
;
1756 end Ureal_M_9_10_36
;
1762 function Ureal_M_10_76
return Ureal
is
1771 function Ureal_Tenth
return Ureal
is