X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=gcc%2Fada%2Furealp.adb;fp=gcc%2Fada%2Furealp.adb;h=0000000000000000000000000000000000000000;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=dd087b885ad9d566950b19ca16630b4ac36edb5e;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/ada/urealp.adb b/gcc/ada/urealp.adb deleted file mode 100644 index dd087b88..00000000 --- a/gcc/ada/urealp.adb +++ /dev/null @@ -1,1472 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- U R E A L P -- --- -- --- B o d y -- --- -- --- $Revision: 1.2.12.1 $ --- -- --- Copyright (C) 1992-2001 Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- --- for more details. You should have received a copy of the GNU General -- --- Public License distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, -- --- MA 02111-1307, USA. -- --- -- --- As a special exception, if other files instantiate generics from this -- --- unit, or you link this unit with other files to produce an executable, -- --- this unit does not by itself cause the resulting executable to be -- --- covered by the GNU General Public License. This exception does not -- --- however invalidate any other reasons why the executable file might be -- --- covered by the GNU Public License. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Alloc; -with Output; use Output; -with Table; -with Tree_IO; use Tree_IO; - -package body Urealp is - - Ureal_First_Entry : constant Ureal := Ureal'Succ (No_Ureal); - -- First subscript allocated in Ureal table (note that we can't just - -- add 1 to No_Ureal, since "+" means something different for Ureals! - - type Ureal_Entry is record - Num : Uint; - -- Numerator (always non-negative) - - Den : Uint; - -- Denominator (always non-zero, always positive if base is zero) - - Rbase : Nat; - -- Base value. If Rbase is zero, then the value is simply Num / Den. - -- If Rbase is non-zero, then the value is Num / (Rbase ** Den) - - Negative : Boolean; - -- Flag set if value is negative - - end record; - - package Ureals is new Table.Table ( - Table_Component_Type => Ureal_Entry, - Table_Index_Type => Ureal, - Table_Low_Bound => Ureal_First_Entry, - Table_Initial => Alloc.Ureals_Initial, - Table_Increment => Alloc.Ureals_Increment, - Table_Name => "Ureals"); - - -- The following universal reals are the values returned by the constant - -- functions. They are initialized by the initialization procedure. - - UR_M_0 : Ureal; - UR_0 : Ureal; - UR_Tenth : Ureal; - UR_Half : Ureal; - UR_1 : Ureal; - UR_2 : Ureal; - UR_10 : Ureal; - UR_100 : Ureal; - UR_2_128 : Ureal; - UR_2_M_128 : Ureal; - - Num_Ureal_Constants : constant := 10; - -- This is used for an assertion check in Tree_Read and Tree_Write to - -- help remember to add values to these routines when we add to the list. - - Normalized_Real : Ureal := No_Ureal; - -- Used to memoize Norm_Num and Norm_Den, if either of these functions - -- is called, this value is set and Normalized_Entry contains the result - -- of the normalization. On subsequent calls, this is used to avoid the - -- call to Normalize if it has already been made. - - Normalized_Entry : Ureal_Entry; - -- Entry built by most recent call to Normalize - - ----------------------- - -- Local Subprograms -- - ----------------------- - - function Decimal_Exponent_Hi (V : Ureal) return Int; - -- Returns an estimate of the exponent of Val represented as a normalized - -- decimal number (non-zero digit before decimal point), The estimate is - -- either correct, or high, but never low. The accuracy of the estimate - -- affects only the efficiency of the comparison routines. - - function Decimal_Exponent_Lo (V : Ureal) return Int; - -- Returns an estimate of the exponent of Val represented as a normalized - -- decimal number (non-zero digit before decimal point), The estimate is - -- either correct, or low, but never high. The accuracy of the estimate - -- affects only the efficiency of the comparison routines. - - function Equivalent_Decimal_Exponent (U : Ureal_Entry) return Int; - -- U is a Ureal entry for which the base value is non-zero, the value - -- returned is the equivalent decimal exponent value, i.e. the value of - -- Den, adjusted as though the base were base 10. The value is rounded - -- to the nearest integer, and so can be one off. - - function Is_Integer (Num, Den : Uint) return Boolean; - -- Return true if the real quotient of Num / Den is an integer value - - function Normalize (Val : Ureal_Entry) return Ureal_Entry; - -- Normalizes the Ureal_Entry by reducing it to lowest terms (with a - -- base value of 0). - - function Same (U1, U2 : Ureal) return Boolean; - pragma Inline (Same); - -- Determines if U1 and U2 are the same Ureal. Note that we cannot use - -- the equals operator for this test, since that tests for equality, - -- not identity. - - function Store_Ureal (Val : Ureal_Entry) return Ureal; - -- This store a new entry in the universal reals table and return - -- its index in the table. - - ------------------------- - -- Decimal_Exponent_Hi -- - ------------------------- - - function Decimal_Exponent_Hi (V : Ureal) return Int is - Val : constant Ureal_Entry := Ureals.Table (V); - - begin - -- Zero always returns zero - - if UR_Is_Zero (V) then - return 0; - - -- For numbers in rational form, get the maximum number of digits in the - -- numerator and the minimum number of digits in the denominator, and - -- subtract. For example: - - -- 1000 / 99 = 1.010E+1 - -- 9999 / 10 = 9.999E+2 - - -- This estimate may of course be high, but that is acceptable - - elsif Val.Rbase = 0 then - return UI_Decimal_Digits_Hi (Val.Num) - - UI_Decimal_Digits_Lo (Val.Den); - - -- For based numbers, just subtract the decimal exponent from the - -- high estimate of the number of digits in the numerator and add - -- one to accommodate possible round off errors for non-decimal - -- bases. For example: - - -- 1_500_000 / 10**4 = 1.50E-2 - - else -- Val.Rbase /= 0 - return UI_Decimal_Digits_Hi (Val.Num) - - Equivalent_Decimal_Exponent (Val) + 1; - end if; - - end Decimal_Exponent_Hi; - - ------------------------- - -- Decimal_Exponent_Lo -- - ------------------------- - - function Decimal_Exponent_Lo (V : Ureal) return Int is - Val : constant Ureal_Entry := Ureals.Table (V); - - begin - -- Zero always returns zero - - if UR_Is_Zero (V) then - return 0; - - -- For numbers in rational form, get min digits in numerator, max digits - -- in denominator, and subtract and subtract one more for possible loss - -- during the division. For example: - - -- 1000 / 99 = 1.010E+1 - -- 9999 / 10 = 9.999E+2 - - -- This estimate may of course be low, but that is acceptable - - elsif Val.Rbase = 0 then - return UI_Decimal_Digits_Lo (Val.Num) - - UI_Decimal_Digits_Hi (Val.Den) - 1; - - -- For based numbers, just subtract the decimal exponent from the - -- low estimate of the number of digits in the numerator and subtract - -- one to accommodate possible round off errors for non-decimal - -- bases. For example: - - -- 1_500_000 / 10**4 = 1.50E-2 - - else -- Val.Rbase /= 0 - return UI_Decimal_Digits_Lo (Val.Num) - - Equivalent_Decimal_Exponent (Val) - 1; - end if; - - end Decimal_Exponent_Lo; - - ----------------- - -- Denominator -- - ----------------- - - function Denominator (Real : Ureal) return Uint is - begin - return Ureals.Table (Real).Den; - end Denominator; - - --------------------------------- - -- Equivalent_Decimal_Exponent -- - --------------------------------- - - function Equivalent_Decimal_Exponent (U : Ureal_Entry) return Int is - - -- The following table is a table of logs to the base 10 - - Logs : constant array (Nat range 1 .. 16) of Long_Float := ( - 1 => 0.000000000000000, - 2 => 0.301029995663981, - 3 => 0.477121254719662, - 4 => 0.602059991327962, - 5 => 0.698970004336019, - 6 => 0.778151250383644, - 7 => 0.845098040014257, - 8 => 0.903089986991944, - 9 => 0.954242509439325, - 10 => 1.000000000000000, - 11 => 1.041392685158230, - 12 => 1.079181246047620, - 13 => 1.113943352306840, - 14 => 1.146128035678240, - 15 => 1.176091259055680, - 16 => 1.204119982655920); - - begin - pragma Assert (U.Rbase /= 0); - return Int (Long_Float (UI_To_Int (U.Den)) * Logs (U.Rbase)); - end Equivalent_Decimal_Exponent; - - ---------------- - -- Initialize -- - ---------------- - - procedure Initialize is - begin - Ureals.Init; - UR_0 := UR_From_Components (Uint_0, Uint_1, 0, False); - UR_M_0 := UR_From_Components (Uint_0, Uint_1, 0, True); - UR_Half := UR_From_Components (Uint_1, Uint_1, 2, False); - UR_Tenth := UR_From_Components (Uint_1, Uint_1, 10, False); - UR_1 := UR_From_Components (Uint_1, Uint_1, 0, False); - UR_2 := UR_From_Components (Uint_1, Uint_Minus_1, 2, False); - UR_10 := UR_From_Components (Uint_1, Uint_Minus_1, 10, False); - UR_100 := UR_From_Components (Uint_1, Uint_Minus_2, 10, False); - UR_2_128 := UR_From_Components (Uint_1, Uint_Minus_128, 2, False); - UR_2_M_128 := UR_From_Components (Uint_1, Uint_128, 2, False); - end Initialize; - - ---------------- - -- Is_Integer -- - ---------------- - - function Is_Integer (Num, Den : Uint) return Boolean is - begin - return (Num / Den) * Den = Num; - end Is_Integer; - - ---------- - -- Mark -- - ---------- - - function Mark return Save_Mark is - begin - return Save_Mark (Ureals.Last); - end Mark; - - -------------- - -- Norm_Den -- - -------------- - - function Norm_Den (Real : Ureal) return Uint is - begin - if not Same (Real, Normalized_Real) then - Normalized_Real := Real; - Normalized_Entry := Normalize (Ureals.Table (Real)); - end if; - - return Normalized_Entry.Den; - end Norm_Den; - - -------------- - -- Norm_Num -- - -------------- - - function Norm_Num (Real : Ureal) return Uint is - begin - if not Same (Real, Normalized_Real) then - Normalized_Real := Real; - Normalized_Entry := Normalize (Ureals.Table (Real)); - end if; - - return Normalized_Entry.Num; - end Norm_Num; - - --------------- - -- Normalize -- - --------------- - - function Normalize (Val : Ureal_Entry) return Ureal_Entry is - J : Uint; - K : Uint; - Tmp : Uint; - Num : Uint; - Den : Uint; - M : constant Uintp.Save_Mark := Uintp.Mark; - - begin - -- Start by setting J to the greatest of the absolute values of the - -- numerator and the denominator (taking into account the base value), - -- and K to the lesser of the two absolute values. The gcd of Num and - -- Den is the gcd of J and K. - - if Val.Rbase = 0 then - J := Val.Num; - K := Val.Den; - - elsif Val.Den < 0 then - J := Val.Num * Val.Rbase ** (-Val.Den); - K := Uint_1; - - else - J := Val.Num; - K := Val.Rbase ** Val.Den; - end if; - - Num := J; - Den := K; - - if K > J then - Tmp := J; - J := K; - K := Tmp; - end if; - - J := UI_GCD (J, K); - Num := Num / J; - Den := Den / J; - Uintp.Release_And_Save (M, Num, Den); - - -- Divide numerator and denominator by gcd and return result - - return (Num => Num, - Den => Den, - Rbase => 0, - Negative => Val.Negative); - end Normalize; - - --------------- - -- Numerator -- - --------------- - - function Numerator (Real : Ureal) return Uint is - begin - return Ureals.Table (Real).Num; - end Numerator; - - -------- - -- pr -- - -------- - - procedure pr (Real : Ureal) is - begin - UR_Write (Real); - Write_Eol; - end pr; - - ----------- - -- Rbase -- - ----------- - - function Rbase (Real : Ureal) return Nat is - begin - return Ureals.Table (Real).Rbase; - end Rbase; - - ------------- - -- Release -- - ------------- - - procedure Release (M : Save_Mark) is - begin - Ureals.Set_Last (Ureal (M)); - end Release; - - ---------- - -- Same -- - ---------- - - function Same (U1, U2 : Ureal) return Boolean is - begin - return Int (U1) = Int (U2); - end Same; - - ----------------- - -- Store_Ureal -- - ----------------- - - function Store_Ureal (Val : Ureal_Entry) return Ureal is - begin - Ureals.Increment_Last; - Ureals.Table (Ureals.Last) := Val; - - -- Normalize representation of signed values - - if Val.Num < 0 then - Ureals.Table (Ureals.Last).Negative := True; - Ureals.Table (Ureals.Last).Num := -Val.Num; - end if; - - return Ureals.Last; - end Store_Ureal; - - --------------- - -- Tree_Read -- - --------------- - - procedure Tree_Read is - begin - pragma Assert (Num_Ureal_Constants = 10); - - Ureals.Tree_Read; - Tree_Read_Int (Int (UR_0)); - Tree_Read_Int (Int (UR_M_0)); - Tree_Read_Int (Int (UR_Tenth)); - Tree_Read_Int (Int (UR_Half)); - Tree_Read_Int (Int (UR_1)); - Tree_Read_Int (Int (UR_2)); - Tree_Read_Int (Int (UR_10)); - Tree_Read_Int (Int (UR_100)); - Tree_Read_Int (Int (UR_2_128)); - Tree_Read_Int (Int (UR_2_M_128)); - - -- Clear the normalization cache - - Normalized_Real := No_Ureal; - end Tree_Read; - - ---------------- - -- Tree_Write -- - ---------------- - - procedure Tree_Write is - begin - pragma Assert (Num_Ureal_Constants = 10); - - Ureals.Tree_Write; - Tree_Write_Int (Int (UR_0)); - Tree_Write_Int (Int (UR_M_0)); - Tree_Write_Int (Int (UR_Tenth)); - Tree_Write_Int (Int (UR_Half)); - Tree_Write_Int (Int (UR_1)); - Tree_Write_Int (Int (UR_2)); - Tree_Write_Int (Int (UR_10)); - Tree_Write_Int (Int (UR_100)); - Tree_Write_Int (Int (UR_2_128)); - Tree_Write_Int (Int (UR_2_M_128)); - end Tree_Write; - - ------------ - -- UR_Abs -- - ------------ - - function UR_Abs (Real : Ureal) return Ureal is - Val : constant Ureal_Entry := Ureals.Table (Real); - - begin - return Store_Ureal ( - (Num => Val.Num, - Den => Val.Den, - Rbase => Val.Rbase, - Negative => False)); - end UR_Abs; - - ------------ - -- UR_Add -- - ------------ - - function UR_Add (Left : Uint; Right : Ureal) return Ureal is - begin - return UR_From_Uint (Left) + Right; - end UR_Add; - - function UR_Add (Left : Ureal; Right : Uint) return Ureal is - begin - return Left + UR_From_Uint (Right); - end UR_Add; - - function UR_Add (Left : Ureal; Right : Ureal) return Ureal is - Lval : Ureal_Entry := Ureals.Table (Left); - Rval : Ureal_Entry := Ureals.Table (Right); - - Num : Uint; - - begin - -- Note, in the temporary Ureal_Entry values used in this procedure, - -- we store the sign as the sign of the numerator (i.e. xxx.Num may - -- be negative, even though in stored entries this can never be so) - - if Lval.Rbase /= 0 and then Lval.Rbase = Rval.Rbase then - - declare - Opd_Min, Opd_Max : Ureal_Entry; - Exp_Min, Exp_Max : Uint; - - begin - if Lval.Negative then - Lval.Num := (-Lval.Num); - end if; - - if Rval.Negative then - Rval.Num := (-Rval.Num); - end if; - - if Lval.Den < Rval.Den then - Exp_Min := Lval.Den; - Exp_Max := Rval.Den; - Opd_Min := Lval; - Opd_Max := Rval; - else - Exp_Min := Rval.Den; - Exp_Max := Lval.Den; - Opd_Min := Rval; - Opd_Max := Lval; - end if; - - Num := - Opd_Min.Num * Lval.Rbase ** (Exp_Max - Exp_Min) + Opd_Max.Num; - - if Num = 0 then - return Store_Ureal ( - (Num => Uint_0, - Den => Uint_1, - Rbase => 0, - Negative => Lval.Negative)); - - else - return Store_Ureal ( - (Num => abs Num, - Den => Exp_Max, - Rbase => Lval.Rbase, - Negative => (Num < 0))); - end if; - end; - - else - declare - Ln : Ureal_Entry := Normalize (Lval); - Rn : Ureal_Entry := Normalize (Rval); - - begin - if Ln.Negative then - Ln.Num := (-Ln.Num); - end if; - - if Rn.Negative then - Rn.Num := (-Rn.Num); - end if; - - Num := (Ln.Num * Rn.Den) + (Rn.Num * Ln.Den); - - if Num = 0 then - return Store_Ureal ( - (Num => Uint_0, - Den => Uint_1, - Rbase => 0, - Negative => Lval.Negative)); - - else - return Store_Ureal ( - Normalize ( - (Num => abs Num, - Den => Ln.Den * Rn.Den, - Rbase => 0, - Negative => (Num < 0)))); - end if; - end; - end if; - end UR_Add; - - ---------------- - -- UR_Ceiling -- - ---------------- - - function UR_Ceiling (Real : Ureal) return Uint is - Val : Ureal_Entry := Normalize (Ureals.Table (Real)); - - begin - if Val.Negative then - return UI_Negate (Val.Num / Val.Den); - else - return (Val.Num + Val.Den - 1) / Val.Den; - end if; - end UR_Ceiling; - - ------------ - -- UR_Div -- - ------------ - - function UR_Div (Left : Uint; Right : Ureal) return Ureal is - begin - return UR_From_Uint (Left) / Right; - end UR_Div; - - function UR_Div (Left : Ureal; Right : Uint) return Ureal is - begin - return Left / UR_From_Uint (Right); - end UR_Div; - - function UR_Div (Left, Right : Ureal) return Ureal is - Lval : constant Ureal_Entry := Ureals.Table (Left); - Rval : constant Ureal_Entry := Ureals.Table (Right); - Rneg : constant Boolean := Rval.Negative xor Lval.Negative; - - begin - pragma Assert (Rval.Num /= Uint_0); - - if Lval.Rbase = 0 then - - if Rval.Rbase = 0 then - return Store_Ureal ( - Normalize ( - (Num => Lval.Num * Rval.Den, - Den => Lval.Den * Rval.Num, - Rbase => 0, - Negative => Rneg))); - - elsif Is_Integer (Lval.Num, Rval.Num * Lval.Den) then - return Store_Ureal ( - (Num => Lval.Num / (Rval.Num * Lval.Den), - Den => (-Rval.Den), - Rbase => Rval.Rbase, - Negative => Rneg)); - - elsif Rval.Den < 0 then - return Store_Ureal ( - Normalize ( - (Num => Lval.Num, - Den => Rval.Rbase ** (-Rval.Den) * - Rval.Num * - Lval.Den, - Rbase => 0, - Negative => Rneg))); - - else - return Store_Ureal ( - Normalize ( - (Num => Lval.Num * Rval.Rbase ** Rval.Den, - Den => Rval.Num * Lval.Den, - Rbase => 0, - Negative => Rneg))); - end if; - - elsif Is_Integer (Lval.Num, Rval.Num) then - - if Rval.Rbase = Lval.Rbase then - return Store_Ureal ( - (Num => Lval.Num / Rval.Num, - Den => Lval.Den - Rval.Den, - Rbase => Lval.Rbase, - Negative => Rneg)); - - elsif Rval.Rbase = 0 then - return Store_Ureal ( - (Num => (Lval.Num / Rval.Num) * Rval.Den, - Den => Lval.Den, - Rbase => Lval.Rbase, - Negative => Rneg)); - - elsif Rval.Den < 0 then - declare - Num, Den : Uint; - - begin - if Lval.Den < 0 then - Num := (Lval.Num / Rval.Num) * (Lval.Rbase ** (-Lval.Den)); - Den := Rval.Rbase ** (-Rval.Den); - else - Num := Lval.Num / Rval.Num; - Den := (Lval.Rbase ** Lval.Den) * - (Rval.Rbase ** (-Rval.Den)); - end if; - - return Store_Ureal ( - (Num => Num, - Den => Den, - Rbase => 0, - Negative => Rneg)); - end; - - else - return Store_Ureal ( - (Num => (Lval.Num / Rval.Num) * - (Rval.Rbase ** Rval.Den), - Den => Lval.Den, - Rbase => Lval.Rbase, - Negative => Rneg)); - end if; - - else - declare - Num, Den : Uint; - - begin - if Lval.Den < 0 then - Num := Lval.Num * (Lval.Rbase ** (-Lval.Den)); - Den := Rval.Num; - - else - Num := Lval.Num; - Den := Rval.Num * (Lval.Rbase ** Lval.Den); - end if; - - if Rval.Rbase /= 0 then - if Rval.Den < 0 then - Den := Den * (Rval.Rbase ** (-Rval.Den)); - else - Num := Num * (Rval.Rbase ** Rval.Den); - end if; - - else - Num := Num * Rval.Den; - end if; - - return Store_Ureal ( - Normalize ( - (Num => Num, - Den => Den, - Rbase => 0, - Negative => Rneg))); - end; - end if; - end UR_Div; - - ----------- - -- UR_Eq -- - ----------- - - function UR_Eq (Left, Right : Ureal) return Boolean is - begin - return not UR_Ne (Left, Right); - end UR_Eq; - - --------------------- - -- UR_Exponentiate -- - --------------------- - - function UR_Exponentiate (Real : Ureal; N : Uint) return Ureal is - Bas : Ureal; - Val : Ureal_Entry; - X : Uint := abs N; - Neg : Boolean; - IBas : Uint; - - begin - -- If base is negative, then the resulting sign depends on whether - -- the exponent is even or odd (even => positive, odd = negative) - - if UR_Is_Negative (Real) then - Neg := (N mod 2) /= 0; - Bas := UR_Negate (Real); - else - Neg := False; - Bas := Real; - end if; - - Val := Ureals.Table (Bas); - - -- If the base is a small integer, then we can return the result in - -- exponential form, which can save a lot of time for junk exponents. - - IBas := UR_Trunc (Bas); - - if IBas <= 16 - and then UR_From_Uint (IBas) = Bas - then - return Store_Ureal ( - (Num => Uint_1, - Den => -N, - Rbase => UI_To_Int (UR_Trunc (Bas)), - Negative => Neg)); - - -- If the exponent is negative then we raise the numerator and the - -- denominator (after normalization) to the absolute value of the - -- exponent and we return the reciprocal. An assert error will happen - -- if the numerator is zero. - - elsif N < 0 then - pragma Assert (Val.Num /= 0); - Val := Normalize (Val); - - return Store_Ureal ( - (Num => Val.Den ** X, - Den => Val.Num ** X, - Rbase => 0, - Negative => Neg)); - - -- If positive, we distinguish the case when the base is not zero, in - -- which case the new denominator is just the product of the old one - -- with the exponent, - - else - if Val.Rbase /= 0 then - - return Store_Ureal ( - (Num => Val.Num ** X, - Den => Val.Den * X, - Rbase => Val.Rbase, - Negative => Neg)); - - -- And when the base is zero, in which case we exponentiate - -- the old denominator. - - else - return Store_Ureal ( - (Num => Val.Num ** X, - Den => Val.Den ** X, - Rbase => 0, - Negative => Neg)); - end if; - end if; - end UR_Exponentiate; - - -------------- - -- UR_Floor -- - -------------- - - function UR_Floor (Real : Ureal) return Uint is - Val : Ureal_Entry := Normalize (Ureals.Table (Real)); - - begin - if Val.Negative then - return UI_Negate ((Val.Num + Val.Den - 1) / Val.Den); - else - return Val.Num / Val.Den; - end if; - end UR_Floor; - - ------------------------- - -- UR_From_Components -- - ------------------------- - - function UR_From_Components - (Num : Uint; - Den : Uint; - Rbase : Nat := 0; - Negative : Boolean := False) - return Ureal - is - begin - return Store_Ureal ( - (Num => Num, - Den => Den, - Rbase => Rbase, - Negative => Negative)); - end UR_From_Components; - - ------------------ - -- UR_From_Uint -- - ------------------ - - function UR_From_Uint (UI : Uint) return Ureal is - begin - return UR_From_Components - (abs UI, Uint_1, Negative => (UI < 0)); - end UR_From_Uint; - - ----------- - -- UR_Ge -- - ----------- - - function UR_Ge (Left, Right : Ureal) return Boolean is - begin - return not (Left < Right); - end UR_Ge; - - ----------- - -- UR_Gt -- - ----------- - - function UR_Gt (Left, Right : Ureal) return Boolean is - begin - return (Right < Left); - end UR_Gt; - - -------------------- - -- UR_Is_Negative -- - -------------------- - - function UR_Is_Negative (Real : Ureal) return Boolean is - begin - return Ureals.Table (Real).Negative; - end UR_Is_Negative; - - -------------------- - -- UR_Is_Positive -- - -------------------- - - function UR_Is_Positive (Real : Ureal) return Boolean is - begin - return not Ureals.Table (Real).Negative - and then Ureals.Table (Real).Num /= 0; - end UR_Is_Positive; - - ---------------- - -- UR_Is_Zero -- - ---------------- - - function UR_Is_Zero (Real : Ureal) return Boolean is - begin - return Ureals.Table (Real).Num = 0; - end UR_Is_Zero; - - ----------- - -- UR_Le -- - ----------- - - function UR_Le (Left, Right : Ureal) return Boolean is - begin - return not (Right < Left); - end UR_Le; - - ----------- - -- UR_Lt -- - ----------- - - function UR_Lt (Left, Right : Ureal) return Boolean is - begin - -- An operand is not less than itself - - if Same (Left, Right) then - return False; - - -- Deal with zero cases - - elsif UR_Is_Zero (Left) then - return UR_Is_Positive (Right); - - elsif UR_Is_Zero (Right) then - return Ureals.Table (Left).Negative; - - -- Different signs are decisive (note we dealt with zero cases) - - elsif Ureals.Table (Left).Negative - and then not Ureals.Table (Right).Negative - then - return True; - - elsif not Ureals.Table (Left).Negative - and then Ureals.Table (Right).Negative - then - return False; - - -- Signs are same, do rapid check based on worst case estimates of - -- decimal exponent, which will often be decisive. Precise test - -- depends on whether operands are positive or negative. - - elsif Decimal_Exponent_Hi (Left) < Decimal_Exponent_Lo (Right) then - return UR_Is_Positive (Left); - - elsif Decimal_Exponent_Lo (Left) > Decimal_Exponent_Hi (Right) then - return UR_Is_Negative (Left); - - -- If we fall through, full gruesome test is required. This happens - -- if the numbers are close together, or in some weird (/=10) base. - - else - declare - Imrk : constant Uintp.Save_Mark := Mark; - Rmrk : constant Urealp.Save_Mark := Mark; - Lval : Ureal_Entry; - Rval : Ureal_Entry; - Result : Boolean; - - begin - Lval := Ureals.Table (Left); - Rval := Ureals.Table (Right); - - -- An optimization. If both numbers are based, then subtract - -- common value of base to avoid unnecessarily giant numbers - - if Lval.Rbase = Rval.Rbase and then Lval.Rbase /= 0 then - if Lval.Den < Rval.Den then - Rval.Den := Rval.Den - Lval.Den; - Lval.Den := Uint_0; - else - Lval.Den := Lval.Den - Rval.Den; - Rval.Den := Uint_0; - end if; - end if; - - Lval := Normalize (Lval); - Rval := Normalize (Rval); - - if Lval.Negative then - Result := (Lval.Num * Rval.Den) > (Rval.Num * Lval.Den); - else - Result := (Lval.Num * Rval.Den) < (Rval.Num * Lval.Den); - end if; - - Release (Imrk); - Release (Rmrk); - return Result; - end; - end if; - end UR_Lt; - - ------------ - -- UR_Max -- - ------------ - - function UR_Max (Left, Right : Ureal) return Ureal is - begin - if Left >= Right then - return Left; - else - return Right; - end if; - end UR_Max; - - ------------ - -- UR_Min -- - ------------ - - function UR_Min (Left, Right : Ureal) return Ureal is - begin - if Left <= Right then - return Left; - else - return Right; - end if; - end UR_Min; - - ------------ - -- UR_Mul -- - ------------ - - function UR_Mul (Left : Uint; Right : Ureal) return Ureal is - begin - return UR_From_Uint (Left) * Right; - end UR_Mul; - - function UR_Mul (Left : Ureal; Right : Uint) return Ureal is - begin - return Left * UR_From_Uint (Right); - end UR_Mul; - - function UR_Mul (Left, Right : Ureal) return Ureal is - Lval : constant Ureal_Entry := Ureals.Table (Left); - Rval : constant Ureal_Entry := Ureals.Table (Right); - Num : Uint := Lval.Num * Rval.Num; - Den : Uint; - Rneg : constant Boolean := Lval.Negative xor Rval.Negative; - - begin - if Lval.Rbase = 0 then - if Rval.Rbase = 0 then - return Store_Ureal ( - Normalize ( - (Num => Num, - Den => Lval.Den * Rval.Den, - Rbase => 0, - Negative => Rneg))); - - elsif Is_Integer (Num, Lval.Den) then - return Store_Ureal ( - (Num => Num / Lval.Den, - Den => Rval.Den, - Rbase => Rval.Rbase, - Negative => Rneg)); - - elsif Rval.Den < 0 then - return Store_Ureal ( - Normalize ( - (Num => Num * (Rval.Rbase ** (-Rval.Den)), - Den => Lval.Den, - Rbase => 0, - Negative => Rneg))); - - else - return Store_Ureal ( - Normalize ( - (Num => Num, - Den => Lval.Den * (Rval.Rbase ** Rval.Den), - Rbase => 0, - Negative => Rneg))); - end if; - - elsif Lval.Rbase = Rval.Rbase then - return Store_Ureal ( - (Num => Num, - Den => Lval.Den + Rval.Den, - Rbase => Lval.Rbase, - Negative => Rneg)); - - elsif Rval.Rbase = 0 then - if Is_Integer (Num, Rval.Den) then - return Store_Ureal ( - (Num => Num / Rval.Den, - Den => Lval.Den, - Rbase => Lval.Rbase, - Negative => Rneg)); - - elsif Lval.Den < 0 then - return Store_Ureal ( - Normalize ( - (Num => Num * (Lval.Rbase ** (-Lval.Den)), - Den => Rval.Den, - Rbase => 0, - Negative => Rneg))); - - else - return Store_Ureal ( - Normalize ( - (Num => Num, - Den => Rval.Den * (Lval.Rbase ** Lval.Den), - Rbase => 0, - Negative => Rneg))); - end if; - - else - Den := Uint_1; - - if Lval.Den < 0 then - Num := Num * (Lval.Rbase ** (-Lval.Den)); - else - Den := Den * (Lval.Rbase ** Lval.Den); - end if; - - if Rval.Den < 0 then - Num := Num * (Rval.Rbase ** (-Rval.Den)); - else - Den := Den * (Rval.Rbase ** Rval.Den); - end if; - - return Store_Ureal ( - Normalize ( - (Num => Num, - Den => Den, - Rbase => 0, - Negative => Rneg))); - end if; - - end UR_Mul; - - ----------- - -- UR_Ne -- - ----------- - - function UR_Ne (Left, Right : Ureal) return Boolean is - begin - -- Quick processing for case of identical Ureal values (note that - -- this also deals with comparing two No_Ureal values). - - if Same (Left, Right) then - return False; - - -- Deal with case of one or other operand is No_Ureal, but not both - - elsif Same (Left, No_Ureal) or else Same (Right, No_Ureal) then - return True; - - -- Do quick check based on number of decimal digits - - elsif Decimal_Exponent_Hi (Left) < Decimal_Exponent_Lo (Right) or else - Decimal_Exponent_Lo (Left) > Decimal_Exponent_Hi (Right) - then - return True; - - -- Otherwise full comparison is required - - else - declare - Imrk : constant Uintp.Save_Mark := Mark; - Rmrk : constant Urealp.Save_Mark := Mark; - Lval : constant Ureal_Entry := Normalize (Ureals.Table (Left)); - Rval : constant Ureal_Entry := Normalize (Ureals.Table (Right)); - Result : Boolean; - - begin - if UR_Is_Zero (Left) then - return not UR_Is_Zero (Right); - - elsif UR_Is_Zero (Right) then - return not UR_Is_Zero (Left); - - -- Both operands are non-zero - - else - Result := - Rval.Negative /= Lval.Negative - or else Rval.Num /= Lval.Num - or else Rval.Den /= Lval.Den; - Release (Imrk); - Release (Rmrk); - return Result; - end if; - end; - end if; - end UR_Ne; - - --------------- - -- UR_Negate -- - --------------- - - function UR_Negate (Real : Ureal) return Ureal is - begin - return Store_Ureal ( - (Num => Ureals.Table (Real).Num, - Den => Ureals.Table (Real).Den, - Rbase => Ureals.Table (Real).Rbase, - Negative => not Ureals.Table (Real).Negative)); - end UR_Negate; - - ------------ - -- UR_Sub -- - ------------ - - function UR_Sub (Left : Uint; Right : Ureal) return Ureal is - begin - return UR_From_Uint (Left) + UR_Negate (Right); - end UR_Sub; - - function UR_Sub (Left : Ureal; Right : Uint) return Ureal is - begin - return Left + UR_From_Uint (-Right); - end UR_Sub; - - function UR_Sub (Left, Right : Ureal) return Ureal is - begin - return Left + UR_Negate (Right); - end UR_Sub; - - ---------------- - -- UR_To_Uint -- - ---------------- - - function UR_To_Uint (Real : Ureal) return Uint is - Val : Ureal_Entry := Normalize (Ureals.Table (Real)); - Res : Uint; - - begin - Res := (Val.Num + (Val.Den / 2)) / Val.Den; - - if Val.Negative then - return UI_Negate (Res); - else - return Res; - end if; - end UR_To_Uint; - - -------------- - -- UR_Trunc -- - -------------- - - function UR_Trunc (Real : Ureal) return Uint is - Val : constant Ureal_Entry := Normalize (Ureals.Table (Real)); - - begin - if Val.Negative then - return -(Val.Num / Val.Den); - else - return Val.Num / Val.Den; - end if; - end UR_Trunc; - - -------------- - -- UR_Write -- - -------------- - - procedure UR_Write (Real : Ureal) is - Val : constant Ureal_Entry := Ureals.Table (Real); - - begin - -- If value is negative, we precede the constant by a minus sign - -- and add an extra layer of parentheses on the outside since the - -- minus sign is part of the value, not a negation operator. - - if Val.Negative then - Write_Str ("(-"); - end if; - - -- Constants in base 10 can be written in normal Ada literal style - -- If the literal is negative enclose in parens to emphasize that - -- it is part of the constant, and not a separate negation operator - - if Val.Rbase = 10 then - - UI_Write (Val.Num / 10); - Write_Char ('.'); - UI_Write (Val.Num mod 10); - - if Val.Den /= 0 then - Write_Char ('E'); - UI_Write (1 - Val.Den); - end if; - - -- Constants in a base other than 10 can still be easily written - -- in normal Ada literal style if the numerator is one. - - elsif Val.Rbase /= 0 and then Val.Num = 1 then - Write_Int (Val.Rbase); - Write_Str ("#1.0#E"); - UI_Write (-Val.Den); - - -- Other constants with a base other than 10 are written using one - -- of the following forms, depending on the sign of the number - -- and the sign of the exponent (= minus denominator value) - - -- (numerator.0*base**exponent) - -- (numerator.0*base**(-exponent)) - - elsif Val.Rbase /= 0 then - Write_Char ('('); - UI_Write (Val.Num, Decimal); - Write_Str (".0*"); - Write_Int (Val.Rbase); - Write_Str ("**"); - - if Val.Den <= 0 then - UI_Write (-Val.Den, Decimal); - - else - Write_Str ("(-"); - UI_Write (Val.Den, Decimal); - Write_Char (')'); - end if; - - Write_Char (')'); - - -- Rational constants with a denominator of 1 can be written as - -- a real literal for the numerator integer. - - elsif Val.Den = 1 then - UI_Write (Val.Num, Decimal); - Write_Str (".0"); - - -- Non-based (rational) constants are written in (num/den) style - - else - Write_Char ('('); - UI_Write (Val.Num, Decimal); - Write_Str (".0/"); - UI_Write (Val.Den, Decimal); - Write_Str (".0)"); - end if; - - -- Add trailing paren for negative values - - if Val.Negative then - Write_Char (')'); - end if; - - end UR_Write; - - ------------- - -- Ureal_0 -- - ------------- - - function Ureal_0 return Ureal is - begin - return UR_0; - end Ureal_0; - - ------------- - -- Ureal_1 -- - ------------- - - function Ureal_1 return Ureal is - begin - return UR_1; - end Ureal_1; - - ------------- - -- Ureal_2 -- - ------------- - - function Ureal_2 return Ureal is - begin - return UR_2; - end Ureal_2; - - -------------- - -- Ureal_10 -- - -------------- - - function Ureal_10 return Ureal is - begin - return UR_10; - end Ureal_10; - - --------------- - -- Ureal_100 -- - --------------- - - function Ureal_100 return Ureal is - begin - return UR_100; - end Ureal_100; - - ----------------- - -- Ureal_2_128 -- - ----------------- - - function Ureal_2_128 return Ureal is - begin - return UR_2_128; - end Ureal_2_128; - - ------------------- - -- Ureal_2_M_128 -- - ------------------- - - function Ureal_2_M_128 return Ureal is - begin - return UR_2_M_128; - end Ureal_2_M_128; - - ---------------- - -- Ureal_Half -- - ---------------- - - function Ureal_Half return Ureal is - begin - return UR_Half; - end Ureal_Half; - - --------------- - -- Ureal_M_0 -- - --------------- - - function Ureal_M_0 return Ureal is - begin - return UR_M_0; - end Ureal_M_0; - - ----------------- - -- Ureal_Tenth -- - ----------------- - - function Ureal_Tenth return Ureal is - begin - return UR_Tenth; - end Ureal_Tenth; - -end Urealp;