From: Eric Botcazou <ebotcazou@adacore.com>
There is no need to keep multiplying the result once it saturates to +Inf.
gcc/ada/ChangeLog:
* libgnat/s-powflt.ads (Maxpow_Exact): Minor comment fix.
* libgnat/s-powlfl.ads (Maxpow_Exact): Likewise.
* libgnat/s-powllf.ads (Maxpow_Exact): Likewise.
* libgnat/s-valrea.adb (Large_Powfive) [1 parameter]: Exit the loop
as soon as the result saturates to +Inf.
(Large_Powfive) [2 parameters]: Likewise.
Tested on x86_64-pc-linux-gnu, committed on master.
---
gcc/ada/libgnat/s-powflt.ads | 2 +-
gcc/ada/libgnat/s-powlfl.ads | 2 +-
gcc/ada/libgnat/s-powllf.ads | 4 ++--
gcc/ada/libgnat/s-valrea.adb | 16 ++++++++++++++++
4 files changed, 20 insertions(+), 4 deletions(-)
@@ -36,7 +36,7 @@ package System.Powten_Flt is
Maxpow_Exact : constant := 10;
-- 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).
+ -- floor (M * log 2 / log 5), where 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;
@@ -36,7 +36,7 @@ package System.Powten_LFlt is
Maxpow_Exact : constant := 22;
-- 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).
+ -- to floor (M * log 2 / log 5), where 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;
@@ -37,8 +37,8 @@ package System.Powten_LLF is
Maxpow_Exact : constant :=
(if Long_Long_Float'Machine_Mantissa = 64 then 27 else 22);
-- 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.
+ -- equal to floor (M * log 2 / log 5), where 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;
@@ -336,6 +336,7 @@ package body System.Val_Real is
pragma Import (Ada, Powfive_300);
for Powfive_300'Address use Powfive_300_Address;
+ H : Double_T;
R : Double_T;
E : Natural;
@@ -359,8 +360,15 @@ package body System.Val_Real is
E := Exp - Maxpow;
end if;
+ -- Accumulate 5**Maxpow into R until E <= Maxpow or R saturates to +Inf
+
while E > Maxpow loop
+ H := R;
R := R * Powfive (Maxpow);
+ if R = H then
+ E := Maxpow;
+ exit;
+ end if;
E := E - Maxpow;
end loop;
@@ -381,6 +389,7 @@ package body System.Val_Real is
pragma Import (Ada, Powfive);
for Powfive'Address use Powfive_Address;
+ H : Double_T;
R : Double_T;
E : Natural;
@@ -407,8 +416,15 @@ package body System.Val_Real is
S := 0;
end if;
+ -- Accumulate 5**Maxpow into R until E <= Maxpow or R saturates to +Inf
+
while E > Maxpow loop
+ H := R;
R := R * Powfive (Maxpow);
+ if R = H then
+ E := Maxpow;
+ exit;
+ end if;
E := E - Maxpow;
end loop;