This commit is contained in:
Marek Lemańczyk committed 2025-10-03 23:51:10 +02:00
commit 4f18a02b02
3 files changed
+50 -4

No files matched your search

@@ -1,5 +1,6 @@
using System;
using System.Buffers.Binary;
using System.Threading;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
@@ -35,6 +36,7 @@ public class Pow2MontgomeryModCycleComputationBenchmarks
// private readonly ulong[] _veryLargeCycles = new ulong[SampleCount];
private readonly Random _random = new(113);
private ulong? _previousPrimeOrder;
public enum InputScale
{
@@ -55,12 +57,12 @@ public class Pow2MontgomeryModCycleComputationBenchmarks
ulong smallModulus = NextSmallOddModulus();
_smallDivisors[i] = CreateMontgomeryDivisorData(smallModulus);
_smallExponents[i] = NextSmallExponent();
_smallCycles[i] = MersenneDivisorCycles.CalculateCycleLength(smallModulus);
_smallCycles[i] = CalculateCycleLengthWithHeuristics(smallModulus);
(ulong largeModulus, ulong largeCycle) = NextLargeModulusAndCycle();
_largeDivisors[i] = CreateMontgomeryDivisorData(largeModulus);
_largeExponents[i] = NextLargeExponent();
_largeCycles[i] = largeCycle;
_largeCycles[i] = CalculateCycleLengthWithHeuristics(largeModulus, largeCycle);
// ulong veryLargeModulus = NextVeryLargeOddModulus();
// _veryLargeDivisors[i] = CreateMontgomeryDivisorData(veryLargeModulus);
@@ -125,6 +127,22 @@ public class Pow2MontgomeryModCycleComputationBenchmarks
return checksum;
}
[Benchmark]
public ulong MontgomeryWithHeuristicCycleComputation()
{
GetData(out ulong[] exponents, out MontgomeryDivisorData[] divisors, out _);
ulong checksum = 0UL;
for (int i = 0; i < SampleCount; i++)
{
ulong cycle = CalculateCycleLengthWithHeuristics(divisors[i].Modulus);
checksum ^= exponents[i].Pow2MontgomeryModWithCycle(cycle, divisors[i]);
}
return checksum;
}
private void GetData(out ulong[] exponents, out MontgomeryDivisorData[] divisors, out ulong[] cycles)
{
switch (Scale)
@@ -202,6 +220,34 @@ public class Pow2MontgomeryModCycleComputationBenchmarks
montgomeryTwoSquared);
}
private ulong CalculateCycleLengthWithHeuristics(ulong modulus, ulong fallbackOrder = 0UL)
{
if (modulus <= 1UL || (modulus & 1UL) == 0UL)
{
return fallbackOrder != 0UL ? fallbackOrder : MersenneDivisorCycles.CalculateCycleLength(modulus);
}
if (!PrimeTester.IsPrimeInternal(modulus, CancellationToken.None))
{
return fallbackOrder != 0UL ? fallbackOrder : MersenneDivisorCycles.CalculateCycleLength(modulus);
}
PrimeOrderCalculator.PrimeOrderResult orderResult = PrimeOrderCalculator.Calculate(
modulus,
_previousPrimeOrder,
PrimeOrderCalculator.PrimeOrderSearchConfig.HeuristicDefault);
if (orderResult.Order != 0UL)
{
_previousPrimeOrder = orderResult.Order;
return orderResult.Order;
}
_previousPrimeOrder = null;
return fallbackOrder != 0UL ? fallbackOrder : MersenneDivisorCycles.CalculateCycleLength(modulus);
}
private static ulong ComputeMontgomeryResidue(ulong value, ulong modulus) => (ulong)((UInt128)value * (UInt128.One << 64) % modulus);
private static ulong ComputeMontgomeryNPrime(ulong modulus)
+1 -1
View File
@@ -807,7 +807,7 @@ public class MersenneDivisorCycles
divisor,
previousOrder: null,
PrimeOrderCalculator.PrimeOrderSearchConfig.HeuristicDefault);
if (orderResult.Status == PrimeOrderCalculator.PrimeOrderStatus.Found && orderResult.Order != 0UL)
if (orderResult.Order != 0UL)
{
return orderResult.Order;
}
+1 -1
View File
@@ -104,7 +104,7 @@ internal static class PrimeOrderCalculator
return new PrimeOrderResult(PrimeOrderStatus.Found, order);
}
return new PrimeOrderResult(PrimeOrderStatus.HeuristicUnresolved, 0UL);
return FinishStrictly(prime, config.Mode);
}
private static PrimeOrderResult FinishStrictly(ulong prime, PrimeOrderMode mode)