mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-22 11:41:07 +08:00
[Ada] Correctly round Value attribute for floating point in more cases
This provides correct rounding in the IEEE 754 sense for the Value attribute of floating-point types in more cases, by switching from tables of powers of 10 to tables of powers of 5 for precomputed values, thus making it possible to use a single divide for denormals and normalized numbers just above them. Although this significantly increases the size of the tables, object files for them are still quite small (1, 2 and 4 KB respectively on x86-64). gcc/ada/ * libgnat/s-powflt.ads (Powfive): New constant array. * libgnat/s-powlfl.ads (Powfive): Likewise. (Powfive_100): New constant. (Powfive_200): Likewise. (Powfive_300): Likewise. * libgnat/s-powllf.ads (Powfive): New constant array. (Powfive_100): New constant. (Powfive_200): Likewise. (Powfive_300): Likewise. * libgnat/s-valflt.ads (Impl): Replace Powten with Powfive and pass Null_Address for the address of large constants. * libgnat/s-vallfl.ads (Impl): Replace Powten with Powfive and pass the address of large constants. * libgnat/s-valllf.ads (Impl): Likewise. * libgnat/s-valrea.ads (System.Val_Real): Replace Powten_Address with Powfive_Address and add Powfive_{1,2,3}00_Address parameters. * libgnat/s-valrea.adb (Is_Large_Type): New boolean constant. (Is_Very_Large_Type): Likewise. (Maxexp32): Change value of 10 to that of 5. (Maxexp64): Likewise. (Maxexp80): Likewise. (Integer_to_Real): Use a combination of tables of powers of 5 and scaling if the base is 10. (Large_Powten): Rename into... (Large_Powfive): ...this. Add support for large constants. (Large_Powfive): New overloaded function for very large exponents.
This commit is contained in:
parent
8b9bbdc362
commit
e9bac0faa1
@ -29,17 +29,41 @@
|
||||
-- --
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- This package provides a powers of ten table used for real conversions
|
||||
-- This package provides tables of powers used for real conversions
|
||||
|
||||
package System.Powten_Flt is
|
||||
pragma Pure;
|
||||
|
||||
Maxpow_Exact : constant := 10;
|
||||
-- Largest power of ten exactly representable with Float. It is equal to
|
||||
-- Largest power of five exactly representable with Float. It is equal to
|
||||
-- floor (M * log 2 / log 5), when M is the size of the mantissa (24).
|
||||
-- It also works for any number of the form 5*(2**N) and in particular 10.
|
||||
|
||||
Maxpow : constant := Maxpow_Exact * 2;
|
||||
-- Largest power of ten exactly representable with a double Float
|
||||
-- Largest power of five exactly representable with double Float
|
||||
|
||||
Powfive : constant array (0 .. Maxpow, 1 .. 2) of Float :=
|
||||
[00 => [5.0**00, 0.0],
|
||||
01 => [5.0**01, 0.0],
|
||||
02 => [5.0**02, 0.0],
|
||||
03 => [5.0**03, 0.0],
|
||||
04 => [5.0**04, 0.0],
|
||||
05 => [5.0**05, 0.0],
|
||||
06 => [5.0**06, 0.0],
|
||||
07 => [5.0**07, 0.0],
|
||||
08 => [5.0**08, 0.0],
|
||||
09 => [5.0**09, 0.0],
|
||||
10 => [5.0**10, 0.0],
|
||||
11 => [5.0**11, 5.0**11 - Float'Machine (5.0**11)],
|
||||
12 => [5.0**12, 5.0**12 - Float'Machine (5.0**12)],
|
||||
13 => [5.0**13, 5.0**13 - Float'Machine (5.0**13)],
|
||||
14 => [5.0**14, 5.0**14 - Float'Machine (5.0**14)],
|
||||
15 => [5.0**15, 5.0**15 - Float'Machine (5.0**15)],
|
||||
16 => [5.0**16, 5.0**16 - Float'Machine (5.0**16)],
|
||||
17 => [5.0**17, 5.0**17 - Float'Machine (5.0**17)],
|
||||
18 => [5.0**18, 5.0**18 - Float'Machine (5.0**18)],
|
||||
19 => [5.0**19, 5.0**19 - Float'Machine (5.0**19)],
|
||||
20 => [5.0**20, 5.0**20 - Float'Machine (5.0**20)]];
|
||||
|
||||
Powten : constant array (0 .. Maxpow, 1 .. 2) of Float :=
|
||||
[00 => [1.0E+00, 0.0],
|
||||
|
@ -29,17 +29,74 @@
|
||||
-- --
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- This package provides a powers of ten table used for real conversions
|
||||
-- This package provides tables of powers used for real conversions
|
||||
|
||||
package System.Powten_LFlt is
|
||||
pragma Pure;
|
||||
|
||||
Maxpow_Exact : constant := 22;
|
||||
-- Largest power of ten exactly representable with Long_Float. It is equal
|
||||
-- Largest power of five exactly representable with Long_Float. It is equal
|
||||
-- to floor (M * log 2 / log 5), when M is the size of the mantissa (53).
|
||||
-- It also works for any number of the form 5*(2**N) and in particular 10.
|
||||
|
||||
Maxpow : constant := Maxpow_Exact * 2;
|
||||
-- Largest power of ten exactly representable with a double Long_Float
|
||||
-- Largest power of five exactly representable with double Long_Float
|
||||
|
||||
Powfive : constant array (0 .. Maxpow, 1 .. 2) of Long_Float :=
|
||||
[00 => [5.0**00, 0.0],
|
||||
01 => [5.0**01, 0.0],
|
||||
02 => [5.0**02, 0.0],
|
||||
03 => [5.0**03, 0.0],
|
||||
04 => [5.0**04, 0.0],
|
||||
05 => [5.0**05, 0.0],
|
||||
06 => [5.0**06, 0.0],
|
||||
07 => [5.0**07, 0.0],
|
||||
08 => [5.0**08, 0.0],
|
||||
09 => [5.0**09, 0.0],
|
||||
10 => [5.0**10, 0.0],
|
||||
11 => [5.0**11, 0.0],
|
||||
12 => [5.0**12, 0.0],
|
||||
13 => [5.0**13, 0.0],
|
||||
14 => [5.0**14, 0.0],
|
||||
15 => [5.0**15, 0.0],
|
||||
16 => [5.0**16, 0.0],
|
||||
17 => [5.0**17, 0.0],
|
||||
18 => [5.0**18, 0.0],
|
||||
19 => [5.0**19, 0.0],
|
||||
20 => [5.0**20, 0.0],
|
||||
21 => [5.0**21, 0.0],
|
||||
22 => [5.0**22, 0.0],
|
||||
23 => [5.0**23, 5.0**23 - Long_Float'Machine (5.0**23)],
|
||||
24 => [5.0**24, 5.0**24 - Long_Float'Machine (5.0**24)],
|
||||
25 => [5.0**25, 5.0**25 - Long_Float'Machine (5.0**25)],
|
||||
26 => [5.0**26, 5.0**26 - Long_Float'Machine (5.0**26)],
|
||||
27 => [5.0**27, 5.0**27 - Long_Float'Machine (5.0**27)],
|
||||
28 => [5.0**28, 5.0**28 - Long_Float'Machine (5.0**28)],
|
||||
29 => [5.0**29, 5.0**29 - Long_Float'Machine (5.0**29)],
|
||||
30 => [5.0**30, 5.0**30 - Long_Float'Machine (5.0**30)],
|
||||
31 => [5.0**31, 5.0**31 - Long_Float'Machine (5.0**31)],
|
||||
32 => [5.0**32, 5.0**32 - Long_Float'Machine (5.0**32)],
|
||||
33 => [5.0**33, 5.0**33 - Long_Float'Machine (5.0**33)],
|
||||
34 => [5.0**34, 5.0**34 - Long_Float'Machine (5.0**34)],
|
||||
35 => [5.0**35, 5.0**35 - Long_Float'Machine (5.0**35)],
|
||||
36 => [5.0**36, 5.0**36 - Long_Float'Machine (5.0**36)],
|
||||
37 => [5.0**37, 5.0**37 - Long_Float'Machine (5.0**37)],
|
||||
38 => [5.0**38, 5.0**38 - Long_Float'Machine (5.0**38)],
|
||||
39 => [5.0**39, 5.0**39 - Long_Float'Machine (5.0**39)],
|
||||
40 => [5.0**40, 5.0**40 - Long_Float'Machine (5.0**40)],
|
||||
41 => [5.0**41, 5.0**41 - Long_Float'Machine (5.0**41)],
|
||||
42 => [5.0**42, 5.0**42 - Long_Float'Machine (5.0**42)],
|
||||
43 => [5.0**43, 5.0**43 - Long_Float'Machine (5.0**43)],
|
||||
44 => [5.0**44, 5.0**44 - Long_Float'Machine (5.0**44)]];
|
||||
|
||||
Powfive_100 : constant array (1 .. 2) of Long_Float :=
|
||||
[5.0**100, 5.0**100 - Long_Float'Machine (5.0**100)];
|
||||
|
||||
Powfive_200 : constant array (1 .. 2) of Long_Float :=
|
||||
[5.0**200, 5.0**200 - Long_Float'Machine (5.0**200)];
|
||||
|
||||
Powfive_300 : constant array (1 .. 2) of Long_Float :=
|
||||
[5.0**300, 5.0**300 - Long_Float'Machine (5.0**300)];
|
||||
|
||||
Powten : constant array (0 .. Maxpow, 1 .. 2) of Long_Float :=
|
||||
[00 => [1.0E+00, 0.0],
|
||||
|
@ -29,19 +29,86 @@
|
||||
-- --
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- This package provides a powers of ten table used for real conversions
|
||||
-- This package provides tables of powers used for real conversions
|
||||
|
||||
package System.Powten_LLF is
|
||||
pragma Pure;
|
||||
|
||||
Maxpow_Exact : constant :=
|
||||
(if Long_Long_Float'Machine_Mantissa = 64 then 27 else 22);
|
||||
-- Largest power of ten exactly representable with Long_Long_Float. It is
|
||||
-- Largest power of five exactly representable with Long_Long_Float. It is
|
||||
-- equal to floor (M * log 2 / log 5), when M is the size of the mantissa
|
||||
-- assumed to be either 64 for IEEE Extended or 53 for IEEE Double.
|
||||
-- It also works for any number of the form 5*(2**N) and in particular 10.
|
||||
|
||||
Maxpow : constant := Maxpow_Exact * 2;
|
||||
-- Largest power of ten exactly representable with a double Long_Long_Float
|
||||
-- Largest power of five exactly representable with double Long_Long_Float
|
||||
|
||||
Powfive : constant array (0 .. 54, 1 .. 2) of Long_Long_Float :=
|
||||
[00 => [5.0**00, 0.0],
|
||||
01 => [5.0**01, 0.0],
|
||||
02 => [5.0**02, 0.0],
|
||||
03 => [5.0**03, 0.0],
|
||||
04 => [5.0**04, 0.0],
|
||||
05 => [5.0**05, 0.0],
|
||||
06 => [5.0**06, 0.0],
|
||||
07 => [5.0**07, 0.0],
|
||||
08 => [5.0**08, 0.0],
|
||||
09 => [5.0**09, 0.0],
|
||||
10 => [5.0**10, 0.0],
|
||||
11 => [5.0**11, 0.0],
|
||||
12 => [5.0**12, 0.0],
|
||||
13 => [5.0**13, 0.0],
|
||||
14 => [5.0**14, 0.0],
|
||||
15 => [5.0**15, 0.0],
|
||||
16 => [5.0**16, 0.0],
|
||||
17 => [5.0**17, 0.0],
|
||||
18 => [5.0**18, 0.0],
|
||||
19 => [5.0**19, 0.0],
|
||||
20 => [5.0**20, 0.0],
|
||||
21 => [5.0**21, 0.0],
|
||||
22 => [5.0**22, 0.0],
|
||||
23 => [5.0**23, 5.0**23 - Long_Long_Float'Machine (5.0**23)],
|
||||
24 => [5.0**24, 5.0**24 - Long_Long_Float'Machine (5.0**24)],
|
||||
25 => [5.0**25, 5.0**25 - Long_Long_Float'Machine (5.0**25)],
|
||||
26 => [5.0**26, 5.0**26 - Long_Long_Float'Machine (5.0**26)],
|
||||
27 => [5.0**27, 5.0**27 - Long_Long_Float'Machine (5.0**27)],
|
||||
28 => [5.0**28, 5.0**28 - Long_Long_Float'Machine (5.0**28)],
|
||||
29 => [5.0**29, 5.0**29 - Long_Long_Float'Machine (5.0**29)],
|
||||
30 => [5.0**30, 5.0**30 - Long_Long_Float'Machine (5.0**30)],
|
||||
31 => [5.0**31, 5.0**31 - Long_Long_Float'Machine (5.0**31)],
|
||||
32 => [5.0**32, 5.0**32 - Long_Long_Float'Machine (5.0**32)],
|
||||
33 => [5.0**33, 5.0**33 - Long_Long_Float'Machine (5.0**33)],
|
||||
34 => [5.0**34, 5.0**34 - Long_Long_Float'Machine (5.0**34)],
|
||||
35 => [5.0**35, 5.0**35 - Long_Long_Float'Machine (5.0**35)],
|
||||
36 => [5.0**36, 5.0**36 - Long_Long_Float'Machine (5.0**36)],
|
||||
37 => [5.0**37, 5.0**37 - Long_Long_Float'Machine (5.0**37)],
|
||||
38 => [5.0**38, 5.0**38 - Long_Long_Float'Machine (5.0**38)],
|
||||
39 => [5.0**39, 5.0**39 - Long_Long_Float'Machine (5.0**39)],
|
||||
40 => [5.0**40, 5.0**40 - Long_Long_Float'Machine (5.0**40)],
|
||||
41 => [5.0**41, 5.0**41 - Long_Long_Float'Machine (5.0**41)],
|
||||
42 => [5.0**42, 5.0**42 - Long_Long_Float'Machine (5.0**42)],
|
||||
43 => [5.0**43, 5.0**43 - Long_Long_Float'Machine (5.0**43)],
|
||||
44 => [5.0**44, 5.0**44 - Long_Long_Float'Machine (5.0**44)],
|
||||
45 => [5.0**45, 5.0**45 - Long_Long_Float'Machine (5.0**45)],
|
||||
46 => [5.0**46, 5.0**46 - Long_Long_Float'Machine (5.0**46)],
|
||||
47 => [5.0**47, 5.0**47 - Long_Long_Float'Machine (5.0**47)],
|
||||
48 => [5.0**48, 5.0**48 - Long_Long_Float'Machine (5.0**48)],
|
||||
49 => [5.0**49, 5.0**49 - Long_Long_Float'Machine (5.0**49)],
|
||||
50 => [5.0**50, 5.0**50 - Long_Long_Float'Machine (5.0**50)],
|
||||
51 => [5.0**51, 5.0**51 - Long_Long_Float'Machine (5.0**51)],
|
||||
52 => [5.0**52, 5.0**52 - Long_Long_Float'Machine (5.0**52)],
|
||||
53 => [5.0**53, 5.0**53 - Long_Long_Float'Machine (5.0**53)],
|
||||
54 => [5.0**54, 5.0**54 - Long_Long_Float'Machine (5.0**54)]];
|
||||
|
||||
Powfive_100 : constant array (1 .. 2) of Long_Long_Float :=
|
||||
[5.0**100, 5.0**100 - Long_Long_Float'Machine (5.0**100)];
|
||||
|
||||
Powfive_200 : constant array (1 .. 2) of Long_Long_Float :=
|
||||
[5.0**200, 5.0**200 - Long_Long_Float'Machine (5.0**200)];
|
||||
|
||||
Powfive_300 : constant array (1 .. 2) of Long_Long_Float :=
|
||||
[5.0**300, 5.0**300 - Long_Long_Float'Machine (5.0**300)];
|
||||
|
||||
Powten : constant array (0 .. 54, 1 .. 2) of Long_Long_Float :=
|
||||
[00 => [1.0E+00, 0.0],
|
||||
|
@ -42,7 +42,10 @@ package System.Val_Flt is
|
||||
package Impl is new Val_Real
|
||||
(Float,
|
||||
System.Powten_Flt.Maxpow,
|
||||
System.Powten_Flt.Powten'Address,
|
||||
System.Powten_Flt.Powfive'Address,
|
||||
System.Null_Address,
|
||||
System.Null_Address,
|
||||
System.Null_Address,
|
||||
Unsigned_Types.Unsigned);
|
||||
|
||||
function Scan_Float
|
||||
|
@ -42,7 +42,10 @@ package System.Val_LFlt is
|
||||
package Impl is new Val_Real
|
||||
(Long_Float,
|
||||
System.Powten_LFlt.Maxpow,
|
||||
System.Powten_LFlt.Powten'Address,
|
||||
System.Powten_LFlt.Powfive'Address,
|
||||
System.Powten_LFlt.Powfive_100'Address,
|
||||
System.Powten_LFlt.Powfive_200'Address,
|
||||
System.Powten_LFlt.Powfive_300'Address,
|
||||
Unsigned_Types.Long_Long_Unsigned);
|
||||
|
||||
function Scan_Long_Float
|
||||
|
@ -42,7 +42,10 @@ package System.Val_LLF is
|
||||
package Impl is new Val_Real
|
||||
(Long_Long_Float,
|
||||
System.Powten_LLF.Maxpow,
|
||||
System.Powten_LLF.Powten'Address,
|
||||
System.Powten_LLF.Powfive'Address,
|
||||
System.Powten_LLF.Powfive_100'Address,
|
||||
System.Powten_LLF.Powfive_200'Address,
|
||||
System.Powten_LLF.Powfive_300'Address,
|
||||
System.Unsigned_Types.Long_Long_Unsigned);
|
||||
|
||||
function Scan_Long_Long_Float
|
||||
|
@ -43,7 +43,11 @@ package body System.Val_Real is
|
||||
pragma Assert (Num'Machine_Mantissa <= Uns'Size);
|
||||
-- We need an unsigned type large enough to represent the mantissa
|
||||
|
||||
Is_Large_Type : constant Boolean := Num'Machine_Mantissa >= 53;
|
||||
-- True if the floating-point type is at least IEEE Double
|
||||
|
||||
Precision_Limit : constant Uns := 2**Num'Machine_Mantissa - 1;
|
||||
-- See below for the rationale
|
||||
|
||||
package Impl is new Value_R (Uns, 2, Precision_Limit, Round => False);
|
||||
|
||||
@ -55,18 +59,21 @@ package body System.Val_Real is
|
||||
|
||||
Maxexp32 : constant array (Base_T) of Positive :=
|
||||
[2 => 127, 3 => 80, 4 => 63, 5 => 55, 6 => 49,
|
||||
7 => 45, 8 => 42, 9 => 40, 10 => 38, 11 => 37,
|
||||
7 => 45, 8 => 42, 9 => 40, 10 => 55, 11 => 37,
|
||||
12 => 35, 13 => 34, 14 => 33, 15 => 32, 16 => 31];
|
||||
-- The actual value for 10 is 38 but we also use scaling for 10
|
||||
|
||||
Maxexp64 : constant array (Base_T) of Positive :=
|
||||
[2 => 1023, 3 => 646, 4 => 511, 5 => 441, 6 => 396,
|
||||
7 => 364, 8 => 341, 9 => 323, 10 => 308, 11 => 296,
|
||||
7 => 364, 8 => 341, 9 => 323, 10 => 441, 11 => 296,
|
||||
12 => 285, 13 => 276, 14 => 268, 15 => 262, 16 => 255];
|
||||
-- The actual value for 10 is 308 but we also use scaling for 10
|
||||
|
||||
Maxexp80 : constant array (Base_T) of Positive :=
|
||||
[2 => 16383, 3 => 10337, 4 => 8191, 5 => 7056, 6 => 6338,
|
||||
7 => 5836, 8 => 5461, 9 => 5168, 10 => 4932, 11 => 4736,
|
||||
7 => 5836, 8 => 5461, 9 => 5168, 10 => 7056, 11 => 4736,
|
||||
12 => 4570, 13 => 4427, 14 => 4303, 15 => 4193, 16 => 4095];
|
||||
-- The actual value for 10 is 4932 but we also use scaling for 10
|
||||
|
||||
package Double_Real is new System.Double_Real (Num);
|
||||
use type Double_Real.Double_T;
|
||||
@ -91,8 +98,11 @@ package body System.Val_Real is
|
||||
Minus : Boolean) return Num;
|
||||
-- Convert the real value from integer to real representation
|
||||
|
||||
function Large_Powten (Exp : Natural) return Double_T;
|
||||
-- Return 10.0**Exp as a double number, where Exp > Maxpow
|
||||
function Large_Powfive (Exp : Natural) return Double_T;
|
||||
-- Return 5.0**Exp as a double number, where Exp > Maxpow
|
||||
|
||||
function Large_Powfive (Exp : Natural; S : out Natural) return Double_T;
|
||||
-- Return Num'Scaling (5.0**Exp, -S) as a double number where Exp > Maxexp
|
||||
|
||||
---------------------
|
||||
-- Integer_to_Real --
|
||||
@ -177,13 +187,13 @@ package body System.Val_Real is
|
||||
|
||||
when 10 =>
|
||||
declare
|
||||
Powten : constant array (0 .. Maxpow) of Double_T;
|
||||
pragma Import (Ada, Powten);
|
||||
for Powten'Address use Powten_Address;
|
||||
Powfive : constant array (0 .. Maxpow) of Double_T;
|
||||
pragma Import (Ada, Powfive);
|
||||
for Powfive'Address use Powfive_Address;
|
||||
|
||||
begin
|
||||
if DS <= Maxpow then
|
||||
D_Val := Powten (DS) * V1 + V2;
|
||||
D_Val := Powfive (DS) * Num'Scaling (V1, DS) + V2;
|
||||
S := Scale (2);
|
||||
|
||||
else
|
||||
@ -224,43 +234,46 @@ package body System.Val_Real is
|
||||
R_Val := Num'Scaling (Double_Real.To_Single (D_Val), S);
|
||||
end;
|
||||
|
||||
-- If the base is 10, use a double implementation for the sake
|
||||
-- of accuracy, to be removed when exponentiation is improved.
|
||||
|
||||
-- When the exponent is positive, we can do the computation
|
||||
-- directly because, if the exponentiation overflows, then
|
||||
-- the final value overflows as well. But when the exponent
|
||||
-- is negative, we may need to do it in two steps to avoid
|
||||
-- an artificial underflow.
|
||||
-- If the base is 10, we use a double implementation for the sake
|
||||
-- of accuracy combining powers of 5 and scaling attribute. Using
|
||||
-- this combination is better than using powers of 10 only because
|
||||
-- the Large_Powfive function may overflow only if the final value
|
||||
-- will also either overflow or underflow, thus making it possible
|
||||
-- to use a single division for the case of negative powers of 10.
|
||||
|
||||
when 10 =>
|
||||
declare
|
||||
Powten : constant array (0 .. Maxpow) of Double_T;
|
||||
pragma Import (Ada, Powten);
|
||||
for Powten'Address use Powten_Address;
|
||||
Powfive : constant array (0 .. Maxpow) of Double_T;
|
||||
pragma Import (Ada, Powfive);
|
||||
for Powfive'Address use Powfive_Address;
|
||||
|
||||
RS : Natural;
|
||||
|
||||
begin
|
||||
if S > 0 then
|
||||
if S <= Maxpow then
|
||||
D_Val := D_Val * Powten (S);
|
||||
D_Val := D_Val * Powfive (S);
|
||||
else
|
||||
D_Val := D_Val * Large_Powten (S);
|
||||
D_Val := D_Val * Large_Powfive (S);
|
||||
end if;
|
||||
|
||||
else
|
||||
if S < -Maxexp then
|
||||
D_Val := D_Val / Large_Powten (Maxexp);
|
||||
S := S + Maxexp;
|
||||
end if;
|
||||
|
||||
if S >= -Maxpow then
|
||||
D_Val := D_Val / Powten (-S);
|
||||
D_Val := D_Val / Powfive (-S);
|
||||
|
||||
-- For small types, typically IEEE Single, the trick
|
||||
-- described above does not fully work.
|
||||
|
||||
elsif not Is_Large_Type and then S < -Maxexp then
|
||||
D_Val := D_Val / Large_Powfive (-S, RS);
|
||||
S := S - RS;
|
||||
|
||||
else
|
||||
D_Val := D_Val / Large_Powten (-S);
|
||||
D_Val := D_Val / Large_Powfive (-S);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
R_Val := Double_Real.To_Single (D_Val);
|
||||
R_Val := Num'Scaling (Double_Real.To_Single (D_Val), S);
|
||||
end;
|
||||
|
||||
-- Implementation for other bases with exponentiation
|
||||
@ -302,14 +315,26 @@ package body System.Val_Real is
|
||||
when Constraint_Error => Bad_Value (Str);
|
||||
end Integer_to_Real;
|
||||
|
||||
------------------
|
||||
-- Large_Powten --
|
||||
------------------
|
||||
-------------------
|
||||
-- Large_Powfive --
|
||||
-------------------
|
||||
|
||||
function Large_Powten (Exp : Natural) return Double_T is
|
||||
Powten : constant array (0 .. Maxpow) of Double_T;
|
||||
pragma Import (Ada, Powten);
|
||||
for Powten'Address use Powten_Address;
|
||||
function Large_Powfive (Exp : Natural) return Double_T is
|
||||
Powfive : constant array (0 .. Maxpow) of Double_T;
|
||||
pragma Import (Ada, Powfive);
|
||||
for Powfive'Address use Powfive_Address;
|
||||
|
||||
Powfive_100 : constant Double_T;
|
||||
pragma Import (Ada, Powfive_100);
|
||||
for Powfive_100'Address use Powfive_100_Address;
|
||||
|
||||
Powfive_200 : constant Double_T;
|
||||
pragma Import (Ada, Powfive_200);
|
||||
for Powfive_200'Address use Powfive_200_Address;
|
||||
|
||||
Powfive_300 : constant Double_T;
|
||||
pragma Import (Ada, Powfive_300);
|
||||
for Powfive_300'Address use Powfive_300_Address;
|
||||
|
||||
R : Double_T;
|
||||
E : Natural;
|
||||
@ -317,18 +342,80 @@ package body System.Val_Real is
|
||||
begin
|
||||
pragma Assert (Exp > Maxpow);
|
||||
|
||||
R := Powten (Maxpow);
|
||||
E := Exp - Maxpow;
|
||||
if Is_Large_Type and then Exp >= 300 then
|
||||
R := Powfive_300;
|
||||
E := Exp - 300;
|
||||
|
||||
elsif Is_Large_Type and then Exp >= 200 then
|
||||
R := Powfive_200;
|
||||
E := Exp - 200;
|
||||
|
||||
elsif Is_Large_Type and then Exp >= 100 then
|
||||
R := Powfive_100;
|
||||
E := Exp - 100;
|
||||
|
||||
else
|
||||
R := Powfive (Maxpow);
|
||||
E := Exp - Maxpow;
|
||||
end if;
|
||||
|
||||
while E > Maxpow loop
|
||||
R := R * Powten (Maxpow);
|
||||
R := R * Powfive (Maxpow);
|
||||
E := E - Maxpow;
|
||||
end loop;
|
||||
|
||||
R := R * Powten (E);
|
||||
R := R * Powfive (E);
|
||||
|
||||
return R;
|
||||
end Large_Powten;
|
||||
end Large_Powfive;
|
||||
|
||||
function Large_Powfive (Exp : Natural; S : out Natural) return Double_T is
|
||||
Maxexp : constant Positive :=
|
||||
(if Num'Size = 32 then Maxexp32 (5)
|
||||
elsif Num'Size = 64 then Maxexp64 (5)
|
||||
elsif Num'Machine_Mantissa = 64 then Maxexp80 (5)
|
||||
else raise Program_Error);
|
||||
-- Maximum exponent of 5 that can fit in Num
|
||||
|
||||
Powfive : constant array (0 .. Maxpow) of Double_T;
|
||||
pragma Import (Ada, Powfive);
|
||||
for Powfive'Address use Powfive_Address;
|
||||
|
||||
R : Double_T;
|
||||
E : Natural;
|
||||
|
||||
begin
|
||||
pragma Assert (Exp > Maxexp);
|
||||
|
||||
pragma Warnings (Off, "-gnatw.a");
|
||||
pragma Assert (not Is_Large_Type);
|
||||
pragma Warnings (On, "-gnatw.a");
|
||||
|
||||
R := Powfive (Maxpow);
|
||||
E := Exp - Maxpow;
|
||||
|
||||
-- If the exponent is not too large, then scale down the result so that
|
||||
-- its final value does not overflow but, if it's too large, then do not
|
||||
-- bother doing it since overflow is just fine. The scaling factor is -3
|
||||
-- for every power of 5 above the maximum, in other words division by 8.
|
||||
|
||||
if Exp - Maxexp <= Maxpow then
|
||||
S := 3 * (Exp - Maxexp);
|
||||
R.Hi := Num'Scaling (R.Hi, -S);
|
||||
R.Lo := Num'Scaling (R.Lo, -S);
|
||||
else
|
||||
S := 0;
|
||||
end if;
|
||||
|
||||
while E > Maxpow loop
|
||||
R := R * Powfive (Maxpow);
|
||||
E := E - Maxpow;
|
||||
end loop;
|
||||
|
||||
R := R * Powfive (E);
|
||||
|
||||
return R;
|
||||
end Large_Powfive;
|
||||
|
||||
---------------
|
||||
-- Scan_Real --
|
||||
|
@ -38,7 +38,13 @@ generic
|
||||
|
||||
Maxpow : Positive;
|
||||
|
||||
Powten_Address : System.Address;
|
||||
Powfive_Address : System.Address;
|
||||
|
||||
Powfive_100_Address : System.Address;
|
||||
|
||||
Powfive_200_Address : System.Address;
|
||||
|
||||
Powfive_300_Address : System.Address;
|
||||
|
||||
type Uns is mod <>;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user