Reuse local variables across modulo helpers

This commit is contained in:
Marek Lemańczyk committed 2025-09-22 19:54:59 +02:00
1 parent 3b8a10a20b
commit 762d205e86
3 files changed
+178 -97

No files matched your search

+34 -30
View File
@@ -121,44 +121,48 @@ public static class UInt128Extensions
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Mod10_8_5_3(this UInt128 value, out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3) public static void Mod10_8_5_3(this UInt128 value, out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3)
{ {
UInt128 temp = value; UInt128 temp = UInt128.Zero;
uint byteSum = 0U; uint byteSum = 0U;
byte current = 0;
uint accumulator = 0U;
do temp = value;
{ do
byteSum += (byte)temp; {
temp >>= 8; current = (byte)temp;
} byteSum += current;
while (temp != UInt128.Zero); temp >>= 8;
}
while (temp != UInt128.Zero);
mod8 = (ulong)value & 7UL; mod8 = (ulong)value & 7UL;
uint mod5Value = byteSum.Mod5();
uint mod3Value = byteSum.Mod3();
accumulator = byteSum.Mod5();
mod5 = accumulator;
mod10 = (mod8 & 1UL) == 0UL mod10 = (mod8 & 1UL) == 0UL
? mod5Value switch ? accumulator switch
{ {
0U => 0UL, 0U => 0UL,
1U => 6UL, 1U => 6UL,
2U => 2UL, 2U => 2UL,
3U => 8UL, 3U => 8UL,
_ => 4UL, _ => 4UL,
} }
: mod5Value switch : accumulator switch
{ {
0U => 5UL, 0U => 5UL,
1U => 1UL, 1U => 1UL,
2U => 7UL, 2U => 7UL,
3U => 3UL, 3U => 3UL,
_ => 9UL, _ => 9UL,
}; };
mod5 = mod5Value; // Reusing accumulator to hold the mod 3 reduction now that the mod 5 value has been stored.
mod3 = mod3Value; accumulator = byteSum.Mod3();
} mod3 = accumulator;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static UInt128 Pow(this UInt128 value, ulong exponent) public static UInt128 Pow(this UInt128 value, ulong exponent)
+37 -9
View File
@@ -9,15 +9,29 @@ public static class UIntExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Mod3(this uint value) public static uint Mod3(this uint value)
{ {
uint quotient = (uint)(((ulong)value * 0xAAAAAAABUL) >> 33); ulong wideValue = 0UL;
return value - quotient * 3U; uint quotient = 0U;
uint remainder = 0U;
wideValue = (ulong)value * 0xAAAAAAABUL;
quotient = (uint)(wideValue >> 33);
remainder = value - quotient * 3U;
return remainder;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Mod5(this uint value) public static uint Mod5(this uint value)
{ {
uint quotient = (uint)(((ulong)value * 0xCCCCCCCDUL) >> 34); ulong wideValue = 0UL;
return value - quotient * 5U; uint quotient = 0U;
uint remainder = 0U;
wideValue = (ulong)value * 0xCCCCCCCDUL;
quotient = (uint)(wideValue >> 34);
remainder = value - quotient * 5U;
return remainder;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -30,11 +44,14 @@ public static class UIntExtensions
public static uint Mod7(this uint value) public static uint Mod7(this uint value)
{ {
uint remainder = 0U; uint remainder = 0U;
uint temp = value; uint temp = 0U;
uint chunk = 0U;
temp = value;
while (temp != 0U) while (temp != 0U)
{ {
remainder += temp & 7U; chunk = temp & 7U;
remainder += chunk;
temp >>= 3; temp >>= 3;
if (remainder >= 7U) if (remainder >= 7U)
{ {
@@ -51,18 +68,29 @@ public static class UIntExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Mod10(this uint value) public static uint Mod10(this uint value)
{ {
return value - (uint)(((ulong)value * 0xCCCCCCCDUL) >> 35) * 10U; ulong wideValue = 0UL;
uint quotient = 0U;
uint remainder = 0U;
wideValue = (ulong)value * 0xCCCCCCCDUL;
quotient = (uint)(wideValue >> 35);
remainder = value - quotient * 10U;
return remainder;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Mod11(this uint value) public static uint Mod11(this uint value)
{ {
uint remainder = 0U; uint remainder = 0U;
uint temp = value; uint temp = 0U;
uint chunk = 0U;
temp = value;
while (temp != 0U) while (temp != 0U)
{ {
remainder += temp & 1023U; chunk = temp & 1023U;
remainder += chunk;
temp >>= 10; temp >>= 10;
remainder -= 11U * (remainder / 11U); remainder -= 11U * (remainder / 11U);
} }
+107 -58
View File
@@ -64,23 +64,26 @@ public static class ULongExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Mod10_8_5_3(this ulong value, out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3) public static void Mod10_8_5_3(this ulong value, out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3)
{ {
ulong temp = value; ulong temp = 0UL;
uint byteSum = 0U; uint byteSum = 0U;
byte current = 0;
uint accumulator = 0U;
temp = value;
do do
{ {
byteSum += (byte)temp; current = (byte)temp;
byteSum += current;
temp >>= 8; temp >>= 8;
} }
while (temp != 0UL); while (temp != 0UL);
mod8 = value & 7UL; mod8 = value & 7UL;
uint mod5Value = byteSum.Mod5(); accumulator = byteSum.Mod5();
uint mod3Value = byteSum.Mod3(); mod5 = accumulator;
mod10 = (mod8 & 1UL) == 0UL mod10 = (mod8 & 1UL) == 0UL
? mod5Value switch ? accumulator switch
{ {
0U => 0UL, 0U => 0UL,
1U => 6UL, 1U => 6UL,
@@ -88,7 +91,7 @@ public static class ULongExtensions
3U => 8UL, 3U => 8UL,
_ => 4UL, _ => 4UL,
} }
: mod5Value switch : accumulator switch
{ {
0U => 5UL, 0U => 5UL,
1U => 1UL, 1U => 1UL,
@@ -97,8 +100,9 @@ public static class ULongExtensions
_ => 9UL, _ => 9UL,
}; };
mod5 = mod5Value; // Reusing accumulator to hold the mod 3 reduction now that the mod 5 value has been stored.
mod3 = mod3Value; accumulator = byteSum.Mod3();
mod3 = accumulator;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -108,12 +112,14 @@ public static class ULongExtensions
uint mod5Accumulator = 0U; uint mod5Accumulator = 0U;
uint mod7Accumulator = 0U; uint mod7Accumulator = 0U;
uint mod11Accumulator = 0U; uint mod11Accumulator = 0U;
ulong temp = value; ulong temp = 0UL;
int index = 0; int index = 0;
byte current = 0;
temp = value;
do do
{ {
byte current = (byte)temp; current = (byte)temp;
mod3Accumulator += current; mod3Accumulator += current;
mod5Accumulator += current; mod5Accumulator += current;
mod7Accumulator += (uint)(current * Mod7ByteCoefficients[index]); mod7Accumulator += (uint)(current * Mod7ByteCoefficients[index]);
@@ -124,16 +130,30 @@ public static class ULongExtensions
} }
while (temp != 0UL); while (temp != 0UL);
mod3 = mod3Accumulator.Mod3(); // Reusing mod3Accumulator to store the reduced mod 3 remainder before exposing it.
mod5 = mod5Accumulator.Mod5(); mod3Accumulator = mod3Accumulator.Mod3();
mod7 = ReduceMod7(mod7Accumulator); // Reusing mod5Accumulator to store the reduced mod 5 remainder before exposing it.
mod11 = ReduceMod11(mod11Accumulator); mod5Accumulator = mod5Accumulator.Mod5();
// Reusing mod7Accumulator to store the reduced mod 7 remainder before exposing it.
mod7Accumulator = (uint)ReduceMod7(mod7Accumulator);
// Reusing mod11Accumulator to store the reduced mod 11 remainder before exposing it.
mod11Accumulator = (uint)ReduceMod11(mod11Accumulator);
mod3 = mod3Accumulator;
mod5 = mod5Accumulator;
mod7 = mod7Accumulator;
mod11 = mod11Accumulator;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Mod10_8_5_3Steps(this ulong value, out ulong step10, out ulong step8, out ulong step5, out ulong step3) public static void Mod10_8_5_3Steps(this ulong value, out ulong step10, out ulong step8, out ulong step5, out ulong step3)
{ {
value.Mod10_8_5_3(out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3); ulong mod10 = 0UL;
ulong mod8 = 0UL;
ulong mod5 = 0UL;
ulong mod3 = 0UL;
value.Mod10_8_5_3(out mod10, out mod8, out mod5, out mod3);
step10 = (mod10 << 1).Mod10(); step10 = (mod10 << 1).Mod10();
step8 = ((mod8 << 1) & 7UL); step8 = ((mod8 << 1) & 7UL);
@@ -145,35 +165,38 @@ public static class ULongExtensions
public static bool IsPrimeCandidate(this ulong n) public static bool IsPrimeCandidate(this ulong n)
{ {
int i = 0; int i = 0;
ulong p; ulong p = 0UL;
uint[] smallPrimes = PrimesGenerator.SmallPrimes; uint[] smallPrimes = PrimesGenerator.SmallPrimes;
ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2; ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
int len = smallPrimes.Length; int len = smallPrimes.Length;
for (; i < len; i++) for (; i < len; i++)
{ {
if (smallPrimesPow2[i] > n) if (smallPrimesPow2[i] > n)
{ {
break; break;
} }
p = smallPrimes[i]; p = smallPrimes[i];
if ((n % p) == 0UL) if ((n % p) == 0UL)
{ {
return n == p; return n == p;
} }
} }
return true; return true;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod10(this ulong value) public static ulong Mod10(this ulong value)
{ {
ulong mod5 = value.Mod5(); ulong mod5 = 0UL;
ulong result = 0UL;
mod5 = value.Mod5();
if ((value & 1UL) == 0UL) if ((value & 1UL) == 0UL)
{ {
return mod5 switch result = mod5 switch
{ {
0UL => 0UL, 0UL => 0UL,
1UL => 6UL, 1UL => 6UL,
@@ -182,15 +205,19 @@ public static class ULongExtensions
_ => 4UL, _ => 4UL,
}; };
} }
else
return mod5 switch
{ {
0UL => 5UL, result = mod5 switch
1UL => 1UL, {
2UL => 7UL, 0UL => 5UL,
3UL => 3UL, 1UL => 1UL,
_ => 9UL, 2UL => 7UL,
}; 3UL => 3UL,
_ => 9UL,
};
}
return result;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -199,10 +226,17 @@ public static class ULongExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod3(this ulong value) public static ulong Mod3(this ulong value)
{ {
uint sum = (uint)(value & 0xFFFFUL); uint sum = 0U;
sum += (uint)((value >> 16) & 0xFFFFUL); ulong temp = 0UL;
sum += (uint)((value >> 32) & 0xFFFFUL);
sum += (uint)((value >> 48) & 0xFFFFUL); temp = value & 0xFFFFUL;
sum = (uint)temp;
temp = (value >> 16) & 0xFFFFUL;
sum += (uint)temp;
temp = (value >> 32) & 0xFFFFUL;
sum += (uint)temp;
temp = (value >> 48) & 0xFFFFUL;
sum += (uint)temp;
return sum.Mod3(); return sum.Mod3();
} }
@@ -210,10 +244,17 @@ public static class ULongExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod5(this ulong value) public static ulong Mod5(this ulong value)
{ {
uint sum = (uint)(value & 0xFFFFUL); uint sum = 0U;
sum += (uint)((value >> 16) & 0xFFFFUL); ulong temp = 0UL;
sum += (uint)((value >> 32) & 0xFFFFUL);
sum += (uint)((value >> 48) & 0xFFFFUL); temp = value & 0xFFFFUL;
sum = (uint)temp;
temp = (value >> 16) & 0xFFFFUL;
sum += (uint)temp;
temp = (value >> 32) & 0xFFFFUL;
sum += (uint)temp;
temp = (value >> 48) & 0xFFFFUL;
sum += (uint)temp;
return sum.Mod5(); return sum.Mod5();
} }
@@ -227,10 +268,14 @@ public static class ULongExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod7(this ulong value) public static ulong Mod7(this ulong value)
{ {
uint low = (uint)value; uint low = 0U;
uint high = (uint)(value >> 32); uint high = 0U;
ulong remainder = 0UL;
ulong remainder = low.Mod7() + (ulong)high.Mod7() * 4UL; low = (uint)value;
high = (uint)(value >> 32);
remainder = low.Mod7() + (ulong)high.Mod7() * 4UL;
while (remainder >= 7UL) while (remainder >= 7UL)
{ {
remainder -= 7UL; remainder -= 7UL;
@@ -242,10 +287,14 @@ public static class ULongExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod11(this ulong value) public static ulong Mod11(this ulong value)
{ {
uint low = (uint)value; uint low = 0U;
uint high = (uint)(value >> 32); uint high = 0U;
ulong remainder = 0UL;
ulong remainder = low.Mod11() + (ulong)high.Mod11() * 4UL; low = (uint)value;
high = (uint)(value >> 32);
remainder = low.Mod11() + (ulong)high.Mod11() * 4UL;
while (remainder >= 11UL) while (remainder >= 11UL)
{ {
remainder -= 11UL; remainder -= 11UL;