From 9d41d78b05f262d638fa205c7d60415321535834 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 13 Oct 2020 09:15:23 +0200 Subject: [PATCH] [Ada] Adjust support for 128-bit integer types in System.Random_Numbers gcc/ada/ * libgnat/s-rannum.adb (Random_Discrete): Specifically deal with the case where the size of the base type is larger than 64 bits. --- gcc/ada/libgnat/s-rannum.adb | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/gcc/ada/libgnat/s-rannum.adb b/gcc/ada/libgnat/s-rannum.adb index e65e6a77233..ab6428f9ff8 100644 --- a/gcc/ada/libgnat/s-rannum.adb +++ b/gcc/ada/libgnat/s-rannum.adb @@ -409,6 +409,41 @@ is elsif Max < Min then raise Constraint_Error; + -- In the 128-bit case, we have to be careful since not all 128-bit + -- unsigned values are representable in GNAT's universal integer. + + elsif Result_Subtype'Base'Size > 64 then + declare + -- Ignore unequal-size warnings since GNAT's handling is correct. + + pragma Warnings ("Z"); + function Conv_To_Unsigned is + new Unchecked_Conversion (Result_Subtype'Base, Unsigned_128); + function Conv_To_Result is + new Unchecked_Conversion (Unsigned_128, Result_Subtype'Base); + pragma Warnings ("z"); + + N : constant Unsigned_128 := + Conv_To_Unsigned (Max) - Conv_To_Unsigned (Min) + 1; + + X, Slop : Unsigned_128; + + begin + if N = 0 then + return Conv_To_Result (Conv_To_Unsigned (Min) + Random (Gen)); + + else + Slop := Unsigned_128'Last rem N + 1; + + loop + X := Random (Gen); + exit when Slop = N or else X <= Unsigned_128'Last - Slop; + end loop; + + return Conv_To_Result (Conv_To_Unsigned (Min) + X rem N); + end if; + end; + -- In the 64-bit case, we have to be careful since not all 64-bit -- unsigned values are representable in GNAT's universal integer. -- 2.30.2