1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-27 12:08:00 +02:00

Fixed large-range int64 Next

This commit is contained in:
Brian Fiete 2025-06-11 10:35:28 +02:00
parent c0a261f715
commit 6708399691

View file

@ -197,14 +197,10 @@ namespace System
==============================================================================*/
public virtual int32 Next(int32 minValue, int32 maxValue)
{
if (minValue > maxValue)
{
Runtime.FatalError();
}
Contract.EndContractBlock();
Debug.Assert(minValue < maxValue);
int64 range = (int64)maxValue - minValue;
if (range <= (int64)Int32.MaxValue)
if (range <= Int32.MaxValue)
{
return ((int32)(Sample() * range) + minValue);
}
@ -214,22 +210,34 @@ namespace System
}
}
/*=====================================Next=====================================
**Returns: An int [minvalue..maxvalue)
**Arguments: minValue -- the least legal value for the Random number.
** maxValue -- One greater than the greatest legal return value.
**Exceptions: None.
==============================================================================*/
public virtual int64 Next(int64 minValue, int64 maxValue)
{
if (minValue > maxValue)
{
Runtime.FatalError();
}
Contract.EndContractBlock();
Debug.Assert(minValue < maxValue);
int64 range = (int64)maxValue - minValue;
if (range <= (int64)Int32.MaxValue)
uint64 range = (uint64)(maxValue - minValue);
if (range <= Int32.MaxValue)
{
return ((int32)(Sample() * range) + minValue);
return ((int64)(Sample() * range) + minValue);
}
else
{
return (int32)((int64)(GetSampleForLargeRange() * range) + minValue);
// In order to ensure we produce equally distributed numbers we reroll the
// range of numbers that would cause unequal distribution
bool is_power_of_2(uint64 x) => x == x & (.)-(int64)x;
uint64 excludeRange = is_power_of_2(range) ? 0 : ~(uint64)0 % range + 1;
uint64 res = 0;
repeat
{
res = NextU64();
}
while (res < excludeRange);
return minValue + (.)(res % range);
}
}
@ -241,21 +249,13 @@ namespace System
==============================================================================*/
public virtual int32 Next(int32 maxValue)
{
if (maxValue < 0)
{
Runtime.FatalError();
}
Contract.EndContractBlock();
Debug.Assert(maxValue >= 0);
return (.)(Sample() * maxValue);
}
public virtual int64 Next(int64 maxValue)
{
if (maxValue < 0)
{
Runtime.FatalError();
}
Contract.EndContractBlock();
Debug.Assert(maxValue >= 0);
return (.)(Sample() * maxValue);
}