]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Restore consistent rounding of 'Value for ordinary fixed-point types
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 26 May 2025 10:21:02 +0000 (12:21 +0200)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Tue, 1 Jul 2025 08:29:44 +0000 (10:29 +0200)
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.

gcc/ada/libgnat/s-valuef.adb

index 6ea22117432de50f6d78deb38840f049d23fa256..1743749f542165c19c5984d1a51403225f0f6939 100644 (file)
@@ -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