https://gcc.gnu.org/g:8247ea5bb5b425746d1860e08aa8d823e3cb2500
commit r17-1456-g8247ea5bb5b425746d1860e08aa8d823e3cb2500 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 f5ed11c06a4a..50f724b060a7 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;
