diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs index b120919..9c60557 100644 --- a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs +++ b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs @@ -77,11 +77,17 @@ internal static partial class PrimeOrderCalculator private static bool TrySpecialMaxCpu(ulong phi, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData) { - ReadOnlySpan factorSpan = factors.Factors; int length = factors.Count; + ReadOnlySpan factorSpan = new(factors.Factors, 0, length); for (int i = 0; i < length; i++) { ulong factor = factorSpan[i].Value; + // Don't uncomment this. If there is division by zero, that means something wrong. + // if (factor == 0UL) + // { + // continue; + // } + ulong reduced = phi / factor; if (Pow2EqualsOneCpu(reduced, prime, divisorData)) { @@ -638,7 +644,7 @@ internal static partial class PrimeOrderCalculator private static bool Pow2EqualsOneCpu(ulong exponent, ulong prime, in MontgomeryDivisorData divisorData) { - // if (IsGpuPow2Allowed) + if (IsGpuPow2Allowed) { ulong remainder = exponent.Pow2MontgomeryModWindowedGpu(divisorData, false); // GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(exponent, prime, out ulong remainder, divisorData); @@ -741,26 +747,26 @@ internal static partial class PrimeOrderCalculator remaining = PopulateSmallPrimeFactorsCpu(value, limit, counts); // } - // int dictionaryCount = counts.Count; - // if (dictionaryCount <= FactorSlotCount) - // { - // int copyIndex = 0; - // foreach (KeyValuePair entry in counts) - // { - // primeSlots[copyIndex] = entry.Key; - // exponentSlots[copyIndex] = entry.Value; - // copyIndex++; - // } + int dictionaryCount = counts.Count; + if (dictionaryCount <= FactorSlotCount) + { + int copyIndex = 0; + foreach (KeyValuePair entry in counts) + { + primeSlots[copyIndex] = entry.Key; + exponentSlots[copyIndex] = entry.Value; + copyIndex++; + } - // factorCount = copyIndex; - // ThreadStaticPools.ReturnUlongIntDictionary(counts); - // counts = null; - // } - // else - // { + factorCount = copyIndex; + ThreadStaticPools.ReturnUlongIntDictionary(counts); + counts = null; + } + else + { useDictionary = true; - // factorCount = dictionaryCount; - // } + factorCount = dictionaryCount; + } } diff --git a/PerfectNumbers.Core/ULongExtensions.cs b/PerfectNumbers.Core/ULongExtensions.cs index cc71a47..78ab92a 100644 --- a/PerfectNumbers.Core/ULongExtensions.cs +++ b/PerfectNumbers.Core/ULongExtensions.cs @@ -330,11 +330,12 @@ public static class ULongExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong Pow2MontgomeryModWindowedCpu(this ulong exponent, in MontgomeryDivisorData divisor, bool keepMontgomery) { - ulong modulus = divisor.Modulus; - if (exponent == 0UL) - { - return keepMontgomery ? divisor.MontgomeryOne : 1UL % modulus; - } + ulong modulus = divisor.Modulus; + // This should never happen in production code. If it does, we need to fix it. + // if (exponent == 0UL) + // { + // return keepMontgomery ? divisor.MontgomeryOne : 1UL % modulus; + // } if (exponent <= Pow2WindowFallbackThreshold) { diff --git a/PerfectNumbers.Core/UnboundedTaskScheduler.cs b/PerfectNumbers.Core/UnboundedTaskScheduler.cs index 40a10e6..82a8b1b 100644 --- a/PerfectNumbers.Core/UnboundedTaskScheduler.cs +++ b/PerfectNumbers.Core/UnboundedTaskScheduler.cs @@ -5,30 +5,32 @@ namespace PerfectNumbers.Core; public sealed class UnboundedTaskScheduler : TaskScheduler { - public static UnboundedTaskScheduler Instance { get; } = new(); + public static UnboundedTaskScheduler Instance { get; } = new(); - private UnboundedTaskScheduler() - { - } + private UnboundedTaskScheduler() + { + ThreadPool.SetMaxThreads(100_000, 100_000); + ThreadPool.SetMinThreads(10_300, 100); + } - public override int MaximumConcurrencyLevel => int.MaxValue; + public override int MaximumConcurrencyLevel => int.MaxValue; - protected override void QueueTask(Task task) - { - ThreadPool.UnsafeQueueUserWorkItem(static state => - { - (UnboundedTaskScheduler Scheduler, Task Task) tuple = ((UnboundedTaskScheduler, Task))state!; - tuple.Scheduler.TryExecuteTask(tuple.Task); - }, (this, task)); - } + protected override void QueueTask(Task task) + { + ThreadPool.UnsafeQueueUserWorkItem(static state => + { + (UnboundedTaskScheduler Scheduler, Task Task) tuple = ((UnboundedTaskScheduler, Task))state!; + tuple.Scheduler.TryExecuteTask(tuple.Task); + }, (this, task)); + } - protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) - { - return TryExecuteTask(task); - } + protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) + { + return TryExecuteTask(task); + } - protected override IEnumerable? GetScheduledTasks() - { - return null; - } + protected override IEnumerable? GetScheduledTasks() + { + return null; + } }