Use heuristic sieves for prime trial division
This commit is contained in:
1 parent
15c229665d
commit
1f7680a465
4 files changed
+235
-211
No files matched your search
@@ -71,9 +71,9 @@ The by-divisor executors (`MersenneNumberDivisorByDivisorCpuTester` and `Mersenn
|
||||
|
||||
* **Residue filters** – The CPU scan maintains rolling residues modulo 10/8/5/3/7/11 to match the filters in `MersenneCpuDivisorScanSession.CheckDivisors`. `HeuristicIsPrime*` must either share the residue update helpers or produce identical stepping deltas so the divisor scanners can reuse the pre-filtered candidate stream without recomputing moduli. The shared `MersenneDivisorResidueStepper` now centralises those modulo calculations so both paths reuse the same state transitions, and the GPU by-divisor tester instantiates the same stepper before filtering candidates.
|
||||
* **Stepper integration** – CPU sessions advance residues and unity checks through `ExponentRemainderStepperCpu` together with `CycleRemainderStepper`; GPU kernels mirror this contract via `ExponentRemainderStepperGpu`. The heuristic implementation must call into these steppers (or emit the same remainder deltas) so the shared stepping state remains aligned across CPU/GPU scans and factor validation.
|
||||
* **Wheel alignment** – The wheel 30/210 sequences emitted by `PrimeTester.CreateHeuristicDivisorEnumerator` now drive both the CPU and GPU by-divisor testers, keeping the divisor cache and kernel inputs in lockstep without bespoke residue loops.
|
||||
* **Divisor streaming API** – `PrimeTester.CreateHeuristicDivisorEnumerator` now feeds `MersenneNumberDivisorByDivisorCpuTester.CheckDivisors` and `MersenneNumberDivisorByDivisorGpuTester.CheckDivisors`, replacing bespoke residue loops while supplying candidates directly to Montgomery preparation and GPU kernels.
|
||||
* **GPU batching** – `HeuristicIsPrimeGpu` streams Group A/B candidates through the same enumerator, packs them into batches controlled by `PrimeTester.HeuristicGpuDivisorBatchSize`, and launches `PrimeTesterKernels.HeuristicTrialDivisionKernel` to test each divisor with standard `%` arithmetic. When GPUs are disabled, the method delegates to the CPU heuristic so fallbacks reuse the same candidate ordering without additional plumbing.
|
||||
* **Wheel alignment** – `HeuristicPrimeSieves` precomputes the wheel 30/210 sequences once at startup so both the heuristic prime tester and the by-divisor executors consume identical Group A/B streams without regenerating residues on every call.
|
||||
* **Divisor streaming API** – `PrimeTester.CreateHeuristicDivisorEnumerator` exposes the same precomputed sieves so by-divisor scans can pull candidates directly into Montgomery preparation and GPU kernels without bespoke residue loops.
|
||||
* **GPU batching** – `HeuristicIsPrimeGpu` streams Group A/B candidates from `HeuristicPrimeSieves`, packs them into batches controlled by `PrimeTester.HeuristicGpuDivisorBatchSize`, and launches `PrimeTesterKernels.HeuristicTrialDivisionKernel` to test each divisor with standard `%` arithmetic. When GPUs are disabled, the method delegates to the CPU heuristic so fallbacks reuse the same candidate ordering without additional plumbing.
|
||||
* **Cycle preparation** – When the heuristic discovers a divisor candidate, it should populate `MontgomeryDivisorData` and expose the computed cycle length (or the need to recompute it) so that `DivisorCycleCache` and `MersenneDivisorCycles` do not duplicate work for the same `(prime, divisor)` pair during factor verification. `PrimeTester.PrepareHeuristicDivisor` together with `PrimeTester.ResolveHeuristicCycleLength` now provides this payload to both CPU and GPU by-divisor scans, and the trial-division summaries capture the data whenever a divisor is found.
|
||||
|
||||
* **Caching contract** – The by-divisor GPU implementation pools `DivisorScanSession` instances and reuses GPU buffers. The heuristic must accept externally allocated spans/buffers for divisor candidates, cycle lengths, and hits so the existing resource pools remain valid.
|
||||
@@ -97,8 +97,8 @@ The following summaries cover the first 500,000 odd composite numbers after remo
|
||||
|
||||
### Heuristic cheat sheet
|
||||
|
||||
* Group A: test `3, 7, 11, 13` and every `d ≡ 3 (mod 10)` up to `⌊√n⌋` (wheel 30).
|
||||
* Group B: test only the allowed endings determined by `n mod 10`, scanning in ascending order (wheel 210) and applying the per-class priority order: `n ≡ 1` → `9` then `1`; `n ≡ 3` → `9` then `7`; `n ≡ 7` → `7` then `1`; `n ≡ 9` → `9`, `7`, `1`.
|
||||
* Group A: test `3, 7, 11, 13` and every `d ≡ 3 (mod 10)` up to `⌊√n⌋` from the precomputed wheel-30 sieve.
|
||||
* Group B: test only the allowed endings determined by `n mod 10`, scanning in ascending order from the wheel-210 sieves and applying the per-class priority order: `n ≡ 1` → `9` then `1`; `n ≡ 3` → `9` then `7`; `n ≡ 7` → `7` then `1`; `n ≡ 9` → `9`, `7`, `1`.
|
||||
* Because `min(B)` is overwhelmingly smaller than `A_max(n)` for the “no Group A divisor” cohort, always start Group B from its smallest candidates instead of resuming above `A_max(n)`.
|
||||
|
||||
## Benchmark Reporting
|
||||
|
||||
Reference in new issue
Block a user