From: Eric Botcazou <ebotca...@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(-) diff --git a/gcc/ada/libgnat/s-powflt.ads b/gcc/ada/libgnat/s-powflt.ads index eadea7f914d..ae904f05617 100644 --- a/gcc/ada/libgnat/s-powflt.ads +++ b/gcc/ada/libgnat/s-powflt.ads @@ -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; diff --git a/gcc/ada/libgnat/s-powlfl.ads b/gcc/ada/libgnat/s-powlfl.ads index 13630fcad40..2bf72d9c17d 100644 --- a/gcc/ada/libgnat/s-powlfl.ads +++ b/gcc/ada/libgnat/s-powlfl.ads @@ -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; diff --git a/gcc/ada/libgnat/s-powllf.ads b/gcc/ada/libgnat/s-powllf.ads index b470ae044de..b184b31ea9c 100644 --- a/gcc/ada/libgnat/s-powllf.ads +++ b/gcc/ada/libgnat/s-powllf.ads @@ -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; diff --git a/gcc/ada/libgnat/s-valrea.adb b/gcc/ada/libgnat/s-valrea.adb index f554280c0ea..3b0f0a99a63 100644 --- a/gcc/ada/libgnat/s-valrea.adb +++ b/gcc/ada/libgnat/s-valrea.adb @@ -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; -- 2.43.0