From: Eric Botcazou <ebotca...@adacore.com>

This restores the rounding of the first scaled divide operation applied to
the extra digits, which yields more consistent results for smalls that are
reciprocal of integers.

gcc/ada/ChangeLog:

        * libgnat/s-valuef.adb (Integer_to_Fixed): Restore rounding of the
        first scaled divide operation.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/libgnat/s-valuef.adb | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/gcc/ada/libgnat/s-valuef.adb b/gcc/ada/libgnat/s-valuef.adb
index 6ea22117432..1743749f542 100644
--- a/gcc/ada/libgnat/s-valuef.adb
+++ b/gcc/ada/libgnat/s-valuef.adb
@@ -97,6 +97,8 @@ package body System.Value_F is
 
    --    V = Q1 + (Q2 + R1) / Num + R2 / (Num * (Base ** 2))
 
+   --  but we get rid of the third term by using a rounding divide for (2a).
+
    --  This works only if Den * (Base ** ScaleB) does not overflow for inputs
    --  corresponding to 'Image. Let S = Num / Den, B = Base and N the scale in
    --  base B of S, i.e. the smallest integer such that B**N * S >= 1. Then,
@@ -125,6 +127,8 @@ package body System.Value_F is
 
    --    V = Q1 + (Q2 + R1) / (Num * (Base ** -ScaleB)) + R2 / (Num * (...))
 
+   --  but we get rid of the third term by using a rounding divide for (2b).
+
    --  This works only if Num * (Base ** -ScaleB) does not overflow for inputs
    --  corresponding to 'Image. With the determination of ScaleB above, we have
 
@@ -300,7 +304,7 @@ package body System.Value_F is
 
       if E > 0 then
          Scaled_Divide (To_Signed (V), Y, Z, Q1, R1, Round => False);
-         Scaled_Divide (To_Signed (Uns (E)), Y, -B**2, Q2, R2, Round => False);
+         Scaled_Divide (To_Signed (Uns (E)), Y, -B**2, Q2, R2, Round => True);
 
          --  Avoid an overflow during the subtraction. Note that Q2 is smaller
          --  than Y and R1 smaller than Z in magnitude, so it is safe to take
-- 
2.43.0

Reply via email to