https://gcc.gnu.org/g:aa8d539b67218c4ad4bb171c789269c6092110b5

commit r15-11269-gaa8d539b67218c4ad4bb171c789269c6092110b5
Author: Eric Botcazou <[email protected]>
Date:   Tue Jun 9 20:51:09 2026 +0200

    Ada: Fix couple of oversights in Big_Integer package
    
    Having too many special cases can be counter-productive as shown here.
    
    gcc/ada/
            PR ada/125695
            * libgnat/s-genbig.adb ("**"): Do not drop the sign on the floor.
            (Big_Exp): Take into account the parity of the exponent for -2.
    
    gcc/testsuite/
            * gnat.dg/bigint1.adb: New  test.

Diff:
---
 gcc/ada/libgnat/s-genbig.adb      |  6 +++---
 gcc/testsuite/gnat.dg/bigint1.adb | 27 +++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/gcc/ada/libgnat/s-genbig.adb b/gcc/ada/libgnat/s-genbig.adb
index 2780305e042b..32feecb7e8ea 100644
--- a/gcc/ada/libgnat/s-genbig.adb
+++ b/gcc/ada/libgnat/s-genbig.adb
@@ -262,7 +262,7 @@ package body System.Generic_Bignums is
          --  X ** 1 is X
 
          when 1 =>
-            return Normalize (X.D);
+            return Normalize (X.D, X.Neg);
 
          --  X ** 2 is X * X
 
@@ -331,14 +331,14 @@ package body System.Generic_Bignums is
       elsif Y.Len > 1 then
          raise Storage_Error with "exponentiation result is too large";
 
-      --  Special case (+/-)2 ** K, where K is 1 .. 31 using a shift
+      --  Special case (+/-)2 ** K, where K is in 1 .. 31, using a left shift
 
       elsif X.Len = 1 and then X.D (1) = 2 and then Y.D (1) < 32 then
          declare
             D : constant Digit_Vector (1 .. 1) :=
                   [Shift_Left (SD'(1), Natural (Y.D (1)))];
          begin
-            return Normalize (D, X.Neg);
+            return Normalize (D, X.Neg and then (Y.D (1) and 1) = 1);
          end;
 
       --  Remaining cases have right operand of one word
diff --git a/gcc/testsuite/gnat.dg/bigint1.adb 
b/gcc/testsuite/gnat.dg/bigint1.adb
new file mode 100644
index 000000000000..92a525e5f537
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/bigint1.adb
@@ -0,0 +1,27 @@
+-- { dg-do run }
+-- { dg-options "-gnat2022 -gnata" }
+
+with Ada.Numerics.Big_Numbers.Big_Integers;
+use Ada.Numerics.Big_Numbers.Big_Integers;
+
+procedure Bigint1 is
+
+  Minus_One   : constant Big_Integer := To_Big_Integer (-1);
+  Minus_Two   : constant Big_Integer := To_Big_Integer (-2);
+  Minus_Three : constant Big_Integer := To_Big_Integer (-3);
+
+begin
+
+  pragma Assert (Minus_One ** 1 = Minus_One);
+  pragma Assert (Minus_One ** 2 = To_Big_Integer (1));
+  pragma Assert (Minus_One ** 3 = Minus_One);
+
+  pragma Assert (Minus_Two ** 1 = Minus_Two);
+  pragma Assert (Minus_Two ** 2 = To_Big_Integer (4));
+  pragma Assert (Minus_Two ** 3 = To_Big_Integer (-8));
+
+  pragma Assert (Minus_Three ** 1 = Minus_Three);
+  pragma Assert (Minus_Three ** 2 = To_Big_Integer (9));
+  pragma Assert (Minus_Three ** 3 = To_Big_Integer (-27));
+
+end;

Reply via email to