Add Exts.ISqrt to avoid fp sqrt calculations.
This commit is contained in:
@@ -202,6 +202,91 @@ namespace OpenRA
|
||||
|
||||
public static Size NextPowerOf2(this Size s) { return new Size(NextPowerOf2(s.Width), NextPowerOf2(s.Height)); }
|
||||
|
||||
public enum ISqrtRoundMode { Floor, Nearest, Ceiling }
|
||||
public static int ISqrt(int number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
|
||||
{
|
||||
if (number < 0)
|
||||
throw new InvalidOperationException("Attempted to calculate the square root of a negative integer: {0}".F(number));
|
||||
|
||||
return (int)ISqrt((uint)number, round);
|
||||
}
|
||||
|
||||
public static uint ISqrt(uint number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
|
||||
{
|
||||
var divisor = 1U << 30;
|
||||
|
||||
var root = 0U;
|
||||
var remainder = number;
|
||||
|
||||
// Find the highest term in the divisor
|
||||
while (divisor > number)
|
||||
divisor >>= 2;
|
||||
|
||||
// Evaluate the root, two bits at a time
|
||||
while (divisor != 0)
|
||||
{
|
||||
if (root + divisor <= remainder)
|
||||
{
|
||||
remainder -= root + divisor;
|
||||
root += 2 * divisor;
|
||||
}
|
||||
|
||||
root >>= 1;
|
||||
divisor >>= 2;
|
||||
}
|
||||
|
||||
// Adjust for other rounding modes
|
||||
if (round == ISqrtRoundMode.Nearest && remainder > root)
|
||||
root += 1;
|
||||
|
||||
else if (round == ISqrtRoundMode.Ceiling && root * root < number)
|
||||
root += 1;
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static long ISqrt(long number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
|
||||
{
|
||||
if (number < 0)
|
||||
throw new InvalidOperationException("Attempted to calculate the square root of a negative integer: {0}".F(number));
|
||||
|
||||
return (long)ISqrt((ulong)number, round);
|
||||
}
|
||||
|
||||
public static ulong ISqrt(ulong number, ISqrtRoundMode round = ISqrtRoundMode.Floor)
|
||||
{
|
||||
var divisor = 1UL << 62;
|
||||
|
||||
var root = 0UL;
|
||||
var remainder = number;
|
||||
|
||||
// Find the highest term in the divisor
|
||||
while (divisor > number)
|
||||
divisor >>= 2;
|
||||
|
||||
// Evaluate the root, two bits at a time
|
||||
while (divisor != 0)
|
||||
{
|
||||
if (root + divisor <= remainder)
|
||||
{
|
||||
remainder -= root + divisor;
|
||||
root += 2 * divisor;
|
||||
}
|
||||
|
||||
root >>= 1;
|
||||
divisor >>= 2;
|
||||
}
|
||||
|
||||
// Adjust for other rounding modes
|
||||
if (round == ISqrtRoundMode.Nearest && remainder > root)
|
||||
root += 1;
|
||||
|
||||
else if (round == ISqrtRoundMode.Ceiling && root * root < number)
|
||||
root += 1;
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static string JoinWith<T>(this IEnumerable<T> ts, string j)
|
||||
{
|
||||
return string.Join(j, ts);
|
||||
|
||||
Reference in New Issue
Block a user