From f49963c4f69475dcbf8bc2b5427c7cb737ff84d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Wed, 29 Oct 2025 01:43:12 +0100 Subject: [PATCH] Restore Math.Sqrt heuristic bound --- .../HeuristicCombinedPrimeTester.cs | 34 +++++++------------ PerfectNumbers.Core/HeuristicPrimeTester.cs | 34 +++++++------------ 2 files changed, 26 insertions(+), 42 deletions(-) diff --git a/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs b/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs index 05c22a8..1ae2880 100644 --- a/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs +++ b/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs @@ -306,33 +306,25 @@ Cleanup: internal static ulong ComputeHeuristicSqrt(ulong n) { - if (n < 2UL) + ulong sqrt = (ulong)Math.Sqrt(n); + UInt128 square = (UInt128)sqrt * sqrt; + + while (square > n) { - return n; + sqrt--; + square = (UInt128)sqrt * sqrt; } - int log2 = BitOperations.Log2(n); - ulong estimate = 1UL << ((log2 + 1) >> 1); - ulong quotient = n / estimate; - - while (estimate > quotient) + ulong next = sqrt + 1UL; + UInt128 nextSquare = (UInt128)next * next; + while (nextSquare <= n) { - estimate = (estimate + quotient) >> 1; - quotient = n / estimate; + sqrt = next; + next++; + nextSquare = (UInt128)next * next; } - while (true) - { - ulong nextEstimate = estimate + 1UL; - if (nextEstimate > n / nextEstimate) - { - break; - } - - estimate = nextEstimate; - } - - return estimate; + return sqrt; } private static ReadOnlySpan GetCombinedDivisors(byte nMod10) diff --git a/PerfectNumbers.Core/HeuristicPrimeTester.cs b/PerfectNumbers.Core/HeuristicPrimeTester.cs index d752147..c3983a1 100644 --- a/PerfectNumbers.Core/HeuristicPrimeTester.cs +++ b/PerfectNumbers.Core/HeuristicPrimeTester.cs @@ -431,33 +431,25 @@ Cleanup: internal static ulong ComputeHeuristicSqrt(ulong n) { - if (n < 2UL) + ulong sqrt = (ulong)Math.Sqrt(n); + UInt128 square = (UInt128)sqrt * sqrt; + + while (square > n) { - return n; + sqrt--; + square = (UInt128)sqrt * sqrt; } - int log2 = BitOperations.Log2(n); - ulong estimate = 1UL << ((log2 + 1) >> 1); - ulong quotient = n / estimate; - - while (estimate > quotient) + ulong next = sqrt + 1UL; + UInt128 nextSquare = (UInt128)next * next; + while (nextSquare <= n) { - estimate = (estimate + quotient) >> 1; - quotient = n / estimate; + sqrt = next; + next++; + nextSquare = (UInt128)next * next; } - while (true) - { - ulong nextEstimate = estimate + 1UL; - if (nextEstimate > n / nextEstimate) - { - break; - } - - estimate = nextEstimate; - } - - return estimate; + return sqrt; } private static ReadOnlySpan GetGroupBEndingOrder(byte nMod10) => nMod10 switch