@@ -237,4 +237,54 @@ TEST(RandomTest, ModDistributionSignPreserving)
237
237
<< " Distribution must map negative numbers using sign preserving modulo" ;
238
238
}
239
239
240
+ TEST (RandomTest, NegativeReturnValues)
241
+ {
242
+ // The bug in vanilla RNG stemming from mod instead of bitmasking means that negative values are possible for
243
+ // non-power of 2 arguments to GenerateRnd
244
+ SetRndSeed (1457187811 );
245
+ EXPECT_EQ (GenerateRnd (3 ), -2 ) << " Unexpected return value for a limit of 3" ;
246
+
247
+ SetRndSeed (1457187811 );
248
+ EXPECT_EQ (GenerateRnd (5 ), -3 ) << " Unexpected return value for a limit of 5" ;
249
+ SetRndSeed (1457187811 );
250
+ EXPECT_EQ (GenerateRnd (6 ), -2 ) << " Unexpected return value for a limit of 6" ;
251
+ SetRndSeed (1457187811 );
252
+ EXPECT_EQ (GenerateRnd (7 ), -1 ) << " Unexpected return value for a limit of 7" ;
253
+
254
+ SetRndSeed (1457187811 );
255
+ EXPECT_EQ (GenerateRnd (11 ), -10 ) << " Unexpected return value for a limit of 11" ;
256
+
257
+ SetRndSeed (1457187811 );
258
+ EXPECT_EQ (GenerateRnd (17 ), -9 ) << " Unexpected return value for a limit of 17" ;
259
+
260
+ SetRndSeed (1457187811 );
261
+ EXPECT_EQ (GenerateRnd (19 ), -12 ) << " Unexpected return value for a limit of 19" ;
262
+
263
+ SetRndSeed (1457187811 );
264
+ EXPECT_EQ (GenerateRnd (22 ), -10 ) << " Unexpected return value for a limit of 22" ;
265
+ SetRndSeed (1457187811 );
266
+ EXPECT_EQ (GenerateRnd (23 ), -16 ) << " Unexpected return value for a limit of 23" ;
267
+
268
+ SetRndSeed (1457187811 );
269
+ EXPECT_EQ (GenerateRnd (25 ), -18 ) << " Unexpected return value for a limit of 25" ;
270
+
271
+ SetRndSeed (1457187811 );
272
+ EXPECT_EQ (GenerateRnd (27 ), -17 ) << " Unexpected return value for a limit of 27" ;
273
+
274
+ SetRndSeed (1457187811 );
275
+ EXPECT_EQ (GenerateRnd (29 ), -27 ) << " Unexpected return value for a limit of 29" ;
276
+
277
+ SetRndSeed (1457187811 );
278
+ EXPECT_EQ (GenerateRnd (31 ), -1 ) << " Unexpected return value for a limit of 31" ;
279
+
280
+ for (int i : { 9 , 10 , 12 , 13 , 14 , 15 , 18 , 20 , 21 , 24 , 26 , 28 , 30 }) {
281
+ SetRndSeed (1457187811 );
282
+ EXPECT_EQ (GenerateRnd (i), -8 ) << " Unexpected return value for a limit of " << i;
283
+ }
284
+
285
+ for (int i = 1 ; i < 32768 ; i *= 2 ) {
286
+ SetRndSeed (1457187811 );
287
+ EXPECT_EQ (GenerateRnd (i), 0 ) << " Expect powers of 2 such as " << i << " to cleanly divide the int_min RNG value " ;
288
+ }
289
+ }
240
290
} // namespace devilution
0 commit comments