The implementation computes an incorrect increment for normalized numbers
with the smallest exponent when the floating-point type does not support
denormalized numbers.

Tested on x86_64-pc-linux-gnu, committed on trunk

gcc/ada/

        * eval_fat.adb (Succ): Add a special case for zero if the type does
        not support denormalized numbers.  Always use the canonical formula
        in other cases and add commentary throughout the function.
diff --git a/gcc/ada/eval_fat.adb b/gcc/ada/eval_fat.adb
--- a/gcc/ada/eval_fat.adb
+++ b/gcc/ada/eval_fat.adb
@@ -729,22 +729,30 @@ package body Eval_Fat is
       New_Frac : T;
 
    begin
+      --  Treat zero as a regular denormalized number if they are supported,
+      --  otherwise return the smallest normalized number.
+
       if UR_Is_Zero (X) then
-         Exp := Emin;
+         if Has_Denormals (RT) then
+            Exp := Emin;
+         else
+            return Scaling (RT, Ureal_1, Emin - 1);
+         end if;
       end if;
 
-      --  Set exponent such that the radix point will be directly following the
-      --  mantissa after scaling.
-
-      if Has_Denormals (RT) or Exp /= Emin then
-         Exp := Exp - Mantissa;
-      else
-         Exp := Exp - 1;
-      end if;
+      --  Multiply the number by 2.0**(Mantissa-Exp) so that the radix point
+      --  will be directly following the mantissa after scaling.
 
+      Exp := Exp - Mantissa;
       Frac := Scaling (RT, X, -Exp);
+
+      --  Round to the neareast integer towards +Inf
+
       New_Frac := Ceiling (RT, Frac);
 
+      --  If the rounding was a NOP, add one, except for -2.0**(Mantissa-1)
+      --  because the exponent is going to be reduced.
+
       if New_Frac = Frac then
          if New_Frac = Scaling (RT, -Ureal_1, Mantissa - 1) then
             New_Frac := New_Frac + Scaling (RT, Ureal_1, Uint_Minus_1);
@@ -753,6 +761,8 @@ package body Eval_Fat is
          end if;
       end if;
 
+      --  Divide back by 2.0**(Mantissa-Exp) to get the final result
+
       return Scaling (RT, New_Frac, Exp);
    end Succ;
 


Reply via email to