1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2001 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 2, 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 COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
35 with Output
; use Output
;
37 with Tree_IO
; use Tree_IO
;
39 package body Urealp
is
41 Ureal_First_Entry
: constant Ureal
:= Ureal
'Succ (No_Ureal
);
42 -- First subscript allocated in Ureal table (note that we can't just
43 -- add 1 to No_Ureal, since "+" means something different for Ureals!
45 type Ureal_Entry
is record
47 -- Numerator (always non-negative)
50 -- Denominator (always non-zero, always positive if base is zero)
53 -- Base value. If Rbase is zero, then the value is simply Num / Den.
54 -- If Rbase is non-zero, then the value is Num / (Rbase ** Den)
57 -- Flag set if value is negative
61 package Ureals
is new Table
.Table
(
62 Table_Component_Type
=> Ureal_Entry
,
63 Table_Index_Type
=> Ureal
,
64 Table_Low_Bound
=> Ureal_First_Entry
,
65 Table_Initial
=> Alloc
.Ureals_Initial
,
66 Table_Increment
=> Alloc
.Ureals_Increment
,
67 Table_Name
=> "Ureals");
69 -- The following universal reals are the values returned by the constant
70 -- functions. They are initialized by the initialization procedure.
83 Num_Ureal_Constants
: constant := 10;
84 -- This is used for an assertion check in Tree_Read and Tree_Write to
85 -- help remember to add values to these routines when we add to the list.
87 Normalized_Real
: Ureal
:= No_Ureal
;
88 -- Used to memoize Norm_Num and Norm_Den, if either of these functions
89 -- is called, this value is set and Normalized_Entry contains the result
90 -- of the normalization. On subsequent calls, this is used to avoid the
91 -- call to Normalize if it has already been made.
93 Normalized_Entry
: Ureal_Entry
;
94 -- Entry built by most recent call to Normalize
96 -----------------------
97 -- Local Subprograms --
98 -----------------------
100 function Decimal_Exponent_Hi
(V
: Ureal
) return Int
;
101 -- Returns an estimate of the exponent of Val represented as a normalized
102 -- decimal number (non-zero digit before decimal point), The estimate is
103 -- either correct, or high, but never low. The accuracy of the estimate
104 -- affects only the efficiency of the comparison routines.
106 function Decimal_Exponent_Lo
(V
: Ureal
) return Int
;
107 -- Returns an estimate of the exponent of Val represented as a normalized
108 -- decimal number (non-zero digit before decimal point), The estimate is
109 -- either correct, or low, but never high. The accuracy of the estimate
110 -- affects only the efficiency of the comparison routines.
112 function Equivalent_Decimal_Exponent
(U
: Ureal_Entry
) return Int
;
113 -- U is a Ureal entry for which the base value is non-zero, the value
114 -- returned is the equivalent decimal exponent value, i.e. the value of
115 -- Den, adjusted as though the base were base 10. The value is rounded
116 -- to the nearest integer, and so can be one off.
118 function Is_Integer
(Num
, Den
: Uint
) return Boolean;
119 -- Return true if the real quotient of Num / Den is an integer value
121 function Normalize
(Val
: Ureal_Entry
) return Ureal_Entry
;
122 -- Normalizes the Ureal_Entry by reducing it to lowest terms (with a
125 function Same
(U1
, U2
: Ureal
) return Boolean;
126 pragma Inline
(Same
);
127 -- Determines if U1 and U2 are the same Ureal. Note that we cannot use
128 -- the equals operator for this test, since that tests for equality,
131 function Store_Ureal
(Val
: Ureal_Entry
) return Ureal
;
132 -- This store a new entry in the universal reals table and return
133 -- its index in the table.
135 -------------------------
136 -- Decimal_Exponent_Hi --
137 -------------------------
139 function Decimal_Exponent_Hi
(V
: Ureal
) return Int
is
140 Val
: constant Ureal_Entry
:= Ureals
.Table
(V
);
143 -- Zero always returns zero
145 if UR_Is_Zero
(V
) then
148 -- For numbers in rational form, get the maximum number of digits in the
149 -- numerator and the minimum number of digits in the denominator, and
150 -- subtract. For example:
152 -- 1000 / 99 = 1.010E+1
153 -- 9999 / 10 = 9.999E+2
155 -- This estimate may of course be high, but that is acceptable
157 elsif Val
.Rbase
= 0 then
158 return UI_Decimal_Digits_Hi
(Val
.Num
) -
159 UI_Decimal_Digits_Lo
(Val
.Den
);
161 -- For based numbers, just subtract the decimal exponent from the
162 -- high estimate of the number of digits in the numerator and add
163 -- one to accommodate possible round off errors for non-decimal
164 -- bases. For example:
166 -- 1_500_000 / 10**4 = 1.50E-2
168 else -- Val.Rbase /= 0
169 return UI_Decimal_Digits_Hi
(Val
.Num
) -
170 Equivalent_Decimal_Exponent
(Val
) + 1;
173 end Decimal_Exponent_Hi
;
175 -------------------------
176 -- Decimal_Exponent_Lo --
177 -------------------------
179 function Decimal_Exponent_Lo
(V
: Ureal
) return Int
is
180 Val
: constant Ureal_Entry
:= Ureals
.Table
(V
);
183 -- Zero always returns zero
185 if UR_Is_Zero
(V
) then
188 -- For numbers in rational form, get min digits in numerator, max digits
189 -- in denominator, and subtract and subtract one more for possible loss
190 -- during the division. For example:
192 -- 1000 / 99 = 1.010E+1
193 -- 9999 / 10 = 9.999E+2
195 -- This estimate may of course be low, but that is acceptable
197 elsif Val
.Rbase
= 0 then
198 return UI_Decimal_Digits_Lo
(Val
.Num
) -
199 UI_Decimal_Digits_Hi
(Val
.Den
) - 1;
201 -- For based numbers, just subtract the decimal exponent from the
202 -- low estimate of the number of digits in the numerator and subtract
203 -- one to accommodate possible round off errors for non-decimal
204 -- bases. For example:
206 -- 1_500_000 / 10**4 = 1.50E-2
208 else -- Val.Rbase /= 0
209 return UI_Decimal_Digits_Lo
(Val
.Num
) -
210 Equivalent_Decimal_Exponent
(Val
) - 1;
213 end Decimal_Exponent_Lo
;
219 function Denominator
(Real
: Ureal
) return Uint
is
221 return Ureals
.Table
(Real
).Den
;
224 ---------------------------------
225 -- Equivalent_Decimal_Exponent --
226 ---------------------------------
228 function Equivalent_Decimal_Exponent
(U
: Ureal_Entry
) return Int
is
230 -- The following table is a table of logs to the base 10
232 Logs
: constant array (Nat
range 1 .. 16) of Long_Float := (
233 1 => 0.000000000000000,
234 2 => 0.301029995663981,
235 3 => 0.477121254719662,
236 4 => 0.602059991327962,
237 5 => 0.698970004336019,
238 6 => 0.778151250383644,
239 7 => 0.845098040014257,
240 8 => 0.903089986991944,
241 9 => 0.954242509439325,
242 10 => 1.000000000000000,
243 11 => 1.041392685158230,
244 12 => 1.079181246047620,
245 13 => 1.113943352306840,
246 14 => 1.146128035678240,
247 15 => 1.176091259055680,
248 16 => 1.204119982655920);
251 pragma Assert
(U
.Rbase
/= 0);
252 return Int
(Long_Float (UI_To_Int
(U
.Den
)) * Logs
(U
.Rbase
));
253 end Equivalent_Decimal_Exponent
;
259 procedure Initialize
is
262 UR_0
:= UR_From_Components
(Uint_0
, Uint_1
, 0, False);
263 UR_M_0
:= UR_From_Components
(Uint_0
, Uint_1
, 0, True);
264 UR_Half
:= UR_From_Components
(Uint_1
, Uint_1
, 2, False);
265 UR_Tenth
:= UR_From_Components
(Uint_1
, Uint_1
, 10, False);
266 UR_1
:= UR_From_Components
(Uint_1
, Uint_1
, 0, False);
267 UR_2
:= UR_From_Components
(Uint_1
, Uint_Minus_1
, 2, False);
268 UR_10
:= UR_From_Components
(Uint_1
, Uint_Minus_1
, 10, False);
269 UR_100
:= UR_From_Components
(Uint_1
, Uint_Minus_2
, 10, False);
270 UR_2_128
:= UR_From_Components
(Uint_1
, Uint_Minus_128
, 2, False);
271 UR_2_M_128
:= UR_From_Components
(Uint_1
, Uint_128
, 2, False);
278 function Is_Integer
(Num
, Den
: Uint
) return Boolean is
280 return (Num
/ Den
) * Den
= Num
;
287 function Mark
return Save_Mark
is
289 return Save_Mark
(Ureals
.Last
);
296 function Norm_Den
(Real
: Ureal
) return Uint
is
298 if not Same
(Real
, Normalized_Real
) then
299 Normalized_Real
:= Real
;
300 Normalized_Entry
:= Normalize
(Ureals
.Table
(Real
));
303 return Normalized_Entry
.Den
;
310 function Norm_Num
(Real
: Ureal
) return Uint
is
312 if not Same
(Real
, Normalized_Real
) then
313 Normalized_Real
:= Real
;
314 Normalized_Entry
:= Normalize
(Ureals
.Table
(Real
));
317 return Normalized_Entry
.Num
;
324 function Normalize
(Val
: Ureal_Entry
) return Ureal_Entry
is
330 M
: constant Uintp
.Save_Mark
:= Uintp
.Mark
;
333 -- Start by setting J to the greatest of the absolute values of the
334 -- numerator and the denominator (taking into account the base value),
335 -- and K to the lesser of the two absolute values. The gcd of Num and
336 -- Den is the gcd of J and K.
338 if Val
.Rbase
= 0 then
342 elsif Val
.Den
< 0 then
343 J
:= Val
.Num
* Val
.Rbase
** (-Val
.Den
);
348 K
:= Val
.Rbase
** Val
.Den
;
363 Uintp
.Release_And_Save
(M
, Num
, Den
);
365 -- Divide numerator and denominator by gcd and return result
370 Negative
=> Val
.Negative
);
377 function Numerator
(Real
: Ureal
) return Uint
is
379 return Ureals
.Table
(Real
).Num
;
386 procedure pr
(Real
: Ureal
) is
396 function Rbase
(Real
: Ureal
) return Nat
is
398 return Ureals
.Table
(Real
).Rbase
;
405 procedure Release
(M
: Save_Mark
) is
407 Ureals
.Set_Last
(Ureal
(M
));
414 function Same
(U1
, U2
: Ureal
) return Boolean is
416 return Int
(U1
) = Int
(U2
);
423 function Store_Ureal
(Val
: Ureal_Entry
) return Ureal
is
425 Ureals
.Increment_Last
;
426 Ureals
.Table
(Ureals
.Last
) := Val
;
428 -- Normalize representation of signed values
431 Ureals
.Table
(Ureals
.Last
).Negative
:= True;
432 Ureals
.Table
(Ureals
.Last
).Num
:= -Val
.Num
;
442 procedure Tree_Read
is
444 pragma Assert
(Num_Ureal_Constants
= 10);
447 Tree_Read_Int
(Int
(UR_0
));
448 Tree_Read_Int
(Int
(UR_M_0
));
449 Tree_Read_Int
(Int
(UR_Tenth
));
450 Tree_Read_Int
(Int
(UR_Half
));
451 Tree_Read_Int
(Int
(UR_1
));
452 Tree_Read_Int
(Int
(UR_2
));
453 Tree_Read_Int
(Int
(UR_10
));
454 Tree_Read_Int
(Int
(UR_100
));
455 Tree_Read_Int
(Int
(UR_2_128
));
456 Tree_Read_Int
(Int
(UR_2_M_128
));
458 -- Clear the normalization cache
460 Normalized_Real
:= No_Ureal
;
467 procedure Tree_Write
is
469 pragma Assert
(Num_Ureal_Constants
= 10);
472 Tree_Write_Int
(Int
(UR_0
));
473 Tree_Write_Int
(Int
(UR_M_0
));
474 Tree_Write_Int
(Int
(UR_Tenth
));
475 Tree_Write_Int
(Int
(UR_Half
));
476 Tree_Write_Int
(Int
(UR_1
));
477 Tree_Write_Int
(Int
(UR_2
));
478 Tree_Write_Int
(Int
(UR_10
));
479 Tree_Write_Int
(Int
(UR_100
));
480 Tree_Write_Int
(Int
(UR_2_128
));
481 Tree_Write_Int
(Int
(UR_2_M_128
));
488 function UR_Abs
(Real
: Ureal
) return Ureal
is
489 Val
: constant Ureal_Entry
:= Ureals
.Table
(Real
);
503 function UR_Add
(Left
: Uint
; Right
: Ureal
) return Ureal
is
505 return UR_From_Uint
(Left
) + Right
;
508 function UR_Add
(Left
: Ureal
; Right
: Uint
) return Ureal
is
510 return Left
+ UR_From_Uint
(Right
);
513 function UR_Add
(Left
: Ureal
; Right
: Ureal
) return Ureal
is
514 Lval
: Ureal_Entry
:= Ureals
.Table
(Left
);
515 Rval
: Ureal_Entry
:= Ureals
.Table
(Right
);
520 -- Note, in the temporary Ureal_Entry values used in this procedure,
521 -- we store the sign as the sign of the numerator (i.e. xxx.Num may
522 -- be negative, even though in stored entries this can never be so)
524 if Lval
.Rbase
/= 0 and then Lval
.Rbase
= Rval
.Rbase
then
527 Opd_Min
, Opd_Max
: Ureal_Entry
;
528 Exp_Min
, Exp_Max
: Uint
;
531 if Lval
.Negative
then
532 Lval
.Num
:= (-Lval
.Num
);
535 if Rval
.Negative
then
536 Rval
.Num
:= (-Rval
.Num
);
539 if Lval
.Den
< Rval
.Den
then
552 Opd_Min
.Num
* Lval
.Rbase
** (Exp_Max
- Exp_Min
) + Opd_Max
.Num
;
559 Negative
=> Lval
.Negative
));
566 Negative
=> (Num
< 0)));
572 Ln
: Ureal_Entry
:= Normalize
(Lval
);
573 Rn
: Ureal_Entry
:= Normalize
(Rval
);
584 Num
:= (Ln
.Num
* Rn
.Den
) + (Rn
.Num
* Ln
.Den
);
591 Negative
=> Lval
.Negative
));
597 Den
=> Ln
.Den
* Rn
.Den
,
599 Negative
=> (Num
< 0))));
609 function UR_Ceiling
(Real
: Ureal
) return Uint
is
610 Val
: Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
614 return UI_Negate
(Val
.Num
/ Val
.Den
);
616 return (Val
.Num
+ Val
.Den
- 1) / Val
.Den
;
624 function UR_Div
(Left
: Uint
; Right
: Ureal
) return Ureal
is
626 return UR_From_Uint
(Left
) / Right
;
629 function UR_Div
(Left
: Ureal
; Right
: Uint
) return Ureal
is
631 return Left
/ UR_From_Uint
(Right
);
634 function UR_Div
(Left
, Right
: Ureal
) return Ureal
is
635 Lval
: constant Ureal_Entry
:= Ureals
.Table
(Left
);
636 Rval
: constant Ureal_Entry
:= Ureals
.Table
(Right
);
637 Rneg
: constant Boolean := Rval
.Negative
xor Lval
.Negative
;
640 pragma Assert
(Rval
.Num
/= Uint_0
);
642 if Lval
.Rbase
= 0 then
644 if Rval
.Rbase
= 0 then
647 (Num
=> Lval
.Num
* Rval
.Den
,
648 Den
=> Lval
.Den
* Rval
.Num
,
652 elsif Is_Integer
(Lval
.Num
, Rval
.Num
* Lval
.Den
) then
654 (Num
=> Lval
.Num
/ (Rval
.Num
* Lval
.Den
),
659 elsif Rval
.Den
< 0 then
663 Den
=> Rval
.Rbase
** (-Rval
.Den
) *
672 (Num
=> Lval
.Num
* Rval
.Rbase
** Rval
.Den
,
673 Den
=> Rval
.Num
* Lval
.Den
,
678 elsif Is_Integer
(Lval
.Num
, Rval
.Num
) then
680 if Rval
.Rbase
= Lval
.Rbase
then
682 (Num
=> Lval
.Num
/ Rval
.Num
,
683 Den
=> Lval
.Den
- Rval
.Den
,
687 elsif Rval
.Rbase
= 0 then
689 (Num
=> (Lval
.Num
/ Rval
.Num
) * Rval
.Den
,
694 elsif Rval
.Den
< 0 then
700 Num
:= (Lval
.Num
/ Rval
.Num
) * (Lval
.Rbase
** (-Lval
.Den
));
701 Den
:= Rval
.Rbase
** (-Rval
.Den
);
703 Num
:= Lval
.Num
/ Rval
.Num
;
704 Den
:= (Lval
.Rbase
** Lval
.Den
) *
705 (Rval
.Rbase
** (-Rval
.Den
));
717 (Num
=> (Lval
.Num
/ Rval
.Num
) *
718 (Rval
.Rbase
** Rval
.Den
),
730 Num
:= Lval
.Num
* (Lval
.Rbase
** (-Lval
.Den
));
735 Den
:= Rval
.Num
* (Lval
.Rbase
** Lval
.Den
);
738 if Rval
.Rbase
/= 0 then
740 Den
:= Den
* (Rval
.Rbase
** (-Rval
.Den
));
742 Num
:= Num
* (Rval
.Rbase
** Rval
.Den
);
746 Num
:= Num
* Rval
.Den
;
763 function UR_Eq
(Left
, Right
: Ureal
) return Boolean is
765 return not UR_Ne
(Left
, Right
);
768 ---------------------
769 -- UR_Exponentiate --
770 ---------------------
772 function UR_Exponentiate
(Real
: Ureal
; N
: Uint
) return Ureal
is
780 -- If base is negative, then the resulting sign depends on whether
781 -- the exponent is even or odd (even => positive, odd = negative)
783 if UR_Is_Negative
(Real
) then
784 Neg
:= (N
mod 2) /= 0;
785 Bas
:= UR_Negate
(Real
);
791 Val
:= Ureals
.Table
(Bas
);
793 -- If the base is a small integer, then we can return the result in
794 -- exponential form, which can save a lot of time for junk exponents.
796 IBas
:= UR_Trunc
(Bas
);
799 and then UR_From_Uint
(IBas
) = Bas
804 Rbase
=> UI_To_Int
(UR_Trunc
(Bas
)),
807 -- If the exponent is negative then we raise the numerator and the
808 -- denominator (after normalization) to the absolute value of the
809 -- exponent and we return the reciprocal. An assert error will happen
810 -- if the numerator is zero.
813 pragma Assert
(Val
.Num
/= 0);
814 Val
:= Normalize
(Val
);
817 (Num
=> Val
.Den
** X
,
822 -- If positive, we distinguish the case when the base is not zero, in
823 -- which case the new denominator is just the product of the old one
824 -- with the exponent,
827 if Val
.Rbase
/= 0 then
830 (Num
=> Val
.Num
** X
,
835 -- And when the base is zero, in which case we exponentiate
836 -- the old denominator.
840 (Num
=> Val
.Num
** X
,
852 function UR_Floor
(Real
: Ureal
) return Uint
is
853 Val
: Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
857 return UI_Negate
((Val
.Num
+ Val
.Den
- 1) / Val
.Den
);
859 return Val
.Num
/ Val
.Den
;
863 -------------------------
864 -- UR_From_Components --
865 -------------------------
867 function UR_From_Components
871 Negative
: Boolean := False)
879 Negative
=> Negative
));
880 end UR_From_Components
;
886 function UR_From_Uint
(UI
: Uint
) return Ureal
is
888 return UR_From_Components
889 (abs UI
, Uint_1
, Negative
=> (UI
< 0));
896 function UR_Ge
(Left
, Right
: Ureal
) return Boolean is
898 return not (Left
< Right
);
905 function UR_Gt
(Left
, Right
: Ureal
) return Boolean is
907 return (Right
< Left
);
914 function UR_Is_Negative
(Real
: Ureal
) return Boolean is
916 return Ureals
.Table
(Real
).Negative
;
923 function UR_Is_Positive
(Real
: Ureal
) return Boolean is
925 return not Ureals
.Table
(Real
).Negative
926 and then Ureals
.Table
(Real
).Num
/= 0;
933 function UR_Is_Zero
(Real
: Ureal
) return Boolean is
935 return Ureals
.Table
(Real
).Num
= 0;
942 function UR_Le
(Left
, Right
: Ureal
) return Boolean is
944 return not (Right
< Left
);
951 function UR_Lt
(Left
, Right
: Ureal
) return Boolean is
953 -- An operand is not less than itself
955 if Same
(Left
, Right
) then
958 -- Deal with zero cases
960 elsif UR_Is_Zero
(Left
) then
961 return UR_Is_Positive
(Right
);
963 elsif UR_Is_Zero
(Right
) then
964 return Ureals
.Table
(Left
).Negative
;
966 -- Different signs are decisive (note we dealt with zero cases)
968 elsif Ureals
.Table
(Left
).Negative
969 and then not Ureals
.Table
(Right
).Negative
973 elsif not Ureals
.Table
(Left
).Negative
974 and then Ureals
.Table
(Right
).Negative
978 -- Signs are same, do rapid check based on worst case estimates of
979 -- decimal exponent, which will often be decisive. Precise test
980 -- depends on whether operands are positive or negative.
982 elsif Decimal_Exponent_Hi
(Left
) < Decimal_Exponent_Lo
(Right
) then
983 return UR_Is_Positive
(Left
);
985 elsif Decimal_Exponent_Lo
(Left
) > Decimal_Exponent_Hi
(Right
) then
986 return UR_Is_Negative
(Left
);
988 -- If we fall through, full gruesome test is required. This happens
989 -- if the numbers are close together, or in some weird (/=10) base.
993 Imrk
: constant Uintp
.Save_Mark
:= Mark
;
994 Rmrk
: constant Urealp
.Save_Mark
:= Mark
;
1000 Lval
:= Ureals
.Table
(Left
);
1001 Rval
:= Ureals
.Table
(Right
);
1003 -- An optimization. If both numbers are based, then subtract
1004 -- common value of base to avoid unnecessarily giant numbers
1006 if Lval
.Rbase
= Rval
.Rbase
and then Lval
.Rbase
/= 0 then
1007 if Lval
.Den
< Rval
.Den
then
1008 Rval
.Den
:= Rval
.Den
- Lval
.Den
;
1011 Lval
.Den
:= Lval
.Den
- Rval
.Den
;
1016 Lval
:= Normalize
(Lval
);
1017 Rval
:= Normalize
(Rval
);
1019 if Lval
.Negative
then
1020 Result
:= (Lval
.Num
* Rval
.Den
) > (Rval
.Num
* Lval
.Den
);
1022 Result
:= (Lval
.Num
* Rval
.Den
) < (Rval
.Num
* Lval
.Den
);
1036 function UR_Max
(Left
, Right
: Ureal
) return Ureal
is
1038 if Left
>= Right
then
1049 function UR_Min
(Left
, Right
: Ureal
) return Ureal
is
1051 if Left
<= Right
then
1062 function UR_Mul
(Left
: Uint
; Right
: Ureal
) return Ureal
is
1064 return UR_From_Uint
(Left
) * Right
;
1067 function UR_Mul
(Left
: Ureal
; Right
: Uint
) return Ureal
is
1069 return Left
* UR_From_Uint
(Right
);
1072 function UR_Mul
(Left
, Right
: Ureal
) return Ureal
is
1073 Lval
: constant Ureal_Entry
:= Ureals
.Table
(Left
);
1074 Rval
: constant Ureal_Entry
:= Ureals
.Table
(Right
);
1075 Num
: Uint
:= Lval
.Num
* Rval
.Num
;
1077 Rneg
: constant Boolean := Lval
.Negative
xor Rval
.Negative
;
1080 if Lval
.Rbase
= 0 then
1081 if Rval
.Rbase
= 0 then
1082 return Store_Ureal
(
1085 Den
=> Lval
.Den
* Rval
.Den
,
1087 Negative
=> Rneg
)));
1089 elsif Is_Integer
(Num
, Lval
.Den
) then
1090 return Store_Ureal
(
1091 (Num
=> Num
/ Lval
.Den
,
1093 Rbase
=> Rval
.Rbase
,
1096 elsif Rval
.Den
< 0 then
1097 return Store_Ureal
(
1099 (Num
=> Num
* (Rval
.Rbase
** (-Rval
.Den
)),
1102 Negative
=> Rneg
)));
1105 return Store_Ureal
(
1108 Den
=> Lval
.Den
* (Rval
.Rbase
** Rval
.Den
),
1110 Negative
=> Rneg
)));
1113 elsif Lval
.Rbase
= Rval
.Rbase
then
1114 return Store_Ureal
(
1116 Den
=> Lval
.Den
+ Rval
.Den
,
1117 Rbase
=> Lval
.Rbase
,
1120 elsif Rval
.Rbase
= 0 then
1121 if Is_Integer
(Num
, Rval
.Den
) then
1122 return Store_Ureal
(
1123 (Num
=> Num
/ Rval
.Den
,
1125 Rbase
=> Lval
.Rbase
,
1128 elsif Lval
.Den
< 0 then
1129 return Store_Ureal
(
1131 (Num
=> Num
* (Lval
.Rbase
** (-Lval
.Den
)),
1134 Negative
=> Rneg
)));
1137 return Store_Ureal
(
1140 Den
=> Rval
.Den
* (Lval
.Rbase
** Lval
.Den
),
1142 Negative
=> Rneg
)));
1148 if Lval
.Den
< 0 then
1149 Num
:= Num
* (Lval
.Rbase
** (-Lval
.Den
));
1151 Den
:= Den
* (Lval
.Rbase
** Lval
.Den
);
1154 if Rval
.Den
< 0 then
1155 Num
:= Num
* (Rval
.Rbase
** (-Rval
.Den
));
1157 Den
:= Den
* (Rval
.Rbase
** Rval
.Den
);
1160 return Store_Ureal
(
1165 Negative
=> Rneg
)));
1174 function UR_Ne
(Left
, Right
: Ureal
) return Boolean is
1176 -- Quick processing for case of identical Ureal values (note that
1177 -- this also deals with comparing two No_Ureal values).
1179 if Same
(Left
, Right
) then
1182 -- Deal with case of one or other operand is No_Ureal, but not both
1184 elsif Same
(Left
, No_Ureal
) or else Same
(Right
, No_Ureal
) then
1187 -- Do quick check based on number of decimal digits
1189 elsif Decimal_Exponent_Hi
(Left
) < Decimal_Exponent_Lo
(Right
) or else
1190 Decimal_Exponent_Lo
(Left
) > Decimal_Exponent_Hi
(Right
)
1194 -- Otherwise full comparison is required
1198 Imrk
: constant Uintp
.Save_Mark
:= Mark
;
1199 Rmrk
: constant Urealp
.Save_Mark
:= Mark
;
1200 Lval
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Left
));
1201 Rval
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Right
));
1205 if UR_Is_Zero
(Left
) then
1206 return not UR_Is_Zero
(Right
);
1208 elsif UR_Is_Zero
(Right
) then
1209 return not UR_Is_Zero
(Left
);
1211 -- Both operands are non-zero
1215 Rval
.Negative
/= Lval
.Negative
1216 or else Rval
.Num
/= Lval
.Num
1217 or else Rval
.Den
/= Lval
.Den
;
1230 function UR_Negate
(Real
: Ureal
) return Ureal
is
1232 return Store_Ureal
(
1233 (Num
=> Ureals
.Table
(Real
).Num
,
1234 Den
=> Ureals
.Table
(Real
).Den
,
1235 Rbase
=> Ureals
.Table
(Real
).Rbase
,
1236 Negative
=> not Ureals
.Table
(Real
).Negative
));
1243 function UR_Sub
(Left
: Uint
; Right
: Ureal
) return Ureal
is
1245 return UR_From_Uint
(Left
) + UR_Negate
(Right
);
1248 function UR_Sub
(Left
: Ureal
; Right
: Uint
) return Ureal
is
1250 return Left
+ UR_From_Uint
(-Right
);
1253 function UR_Sub
(Left
, Right
: Ureal
) return Ureal
is
1255 return Left
+ UR_Negate
(Right
);
1262 function UR_To_Uint
(Real
: Ureal
) return Uint
is
1263 Val
: Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
1267 Res
:= (Val
.Num
+ (Val
.Den
/ 2)) / Val
.Den
;
1269 if Val
.Negative
then
1270 return UI_Negate
(Res
);
1280 function UR_Trunc
(Real
: Ureal
) return Uint
is
1281 Val
: constant Ureal_Entry
:= Normalize
(Ureals
.Table
(Real
));
1284 if Val
.Negative
then
1285 return -(Val
.Num
/ Val
.Den
);
1287 return Val
.Num
/ Val
.Den
;
1295 procedure UR_Write
(Real
: Ureal
) is
1296 Val
: constant Ureal_Entry
:= Ureals
.Table
(Real
);
1299 -- If value is negative, we precede the constant by a minus sign
1300 -- and add an extra layer of parentheses on the outside since the
1301 -- minus sign is part of the value, not a negation operator.
1303 if Val
.Negative
then
1307 -- Constants in base 10 can be written in normal Ada literal style
1308 -- If the literal is negative enclose in parens to emphasize that
1309 -- it is part of the constant, and not a separate negation operator
1311 if Val
.Rbase
= 10 then
1313 UI_Write
(Val
.Num
/ 10);
1315 UI_Write
(Val
.Num
mod 10);
1317 if Val
.Den
/= 0 then
1319 UI_Write
(1 - Val
.Den
);
1322 -- Constants in a base other than 10 can still be easily written
1323 -- in normal Ada literal style if the numerator is one.
1325 elsif Val
.Rbase
/= 0 and then Val
.Num
= 1 then
1326 Write_Int
(Val
.Rbase
);
1327 Write_Str
("#1.0#E");
1328 UI_Write
(-Val
.Den
);
1330 -- Other constants with a base other than 10 are written using one
1331 -- of the following forms, depending on the sign of the number
1332 -- and the sign of the exponent (= minus denominator value)
1334 -- (numerator.0*base**exponent)
1335 -- (numerator.0*base**(-exponent))
1337 elsif Val
.Rbase
/= 0 then
1339 UI_Write
(Val
.Num
, Decimal
);
1341 Write_Int
(Val
.Rbase
);
1344 if Val
.Den
<= 0 then
1345 UI_Write
(-Val
.Den
, Decimal
);
1349 UI_Write
(Val
.Den
, Decimal
);
1355 -- Rational constants with a denominator of 1 can be written as
1356 -- a real literal for the numerator integer.
1358 elsif Val
.Den
= 1 then
1359 UI_Write
(Val
.Num
, Decimal
);
1362 -- Non-based (rational) constants are written in (num/den) style
1366 UI_Write
(Val
.Num
, Decimal
);
1368 UI_Write
(Val
.Den
, Decimal
);
1372 -- Add trailing paren for negative values
1374 if Val
.Negative
then
1384 function Ureal_0
return Ureal
is
1393 function Ureal_1
return Ureal
is
1402 function Ureal_2
return Ureal
is
1411 function Ureal_10
return Ureal
is
1420 function Ureal_100
return Ureal
is
1429 function Ureal_2_128
return Ureal
is
1438 function Ureal_2_M_128
return Ureal
is
1447 function Ureal_Half
return Ureal
is
1456 function Ureal_M_0
return Ureal
is
1465 function Ureal_Tenth
return Ureal
is