From 84451aac4d34397d1e84daaf981a4c8f6c2532ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Sat, 13 Sep 2025 11:07:32 +0200 Subject: [PATCH] Add regression test for divisor cycle GPU generation --- .../MersenneDivisorCyclesGenerateGpuTests.cs | 55 +++++++++++++++++++ .../MersenneNumberResidueGpuTesterTests.cs | 1 + PerfectNumbers.Core/MersenneDivisorCycles.cs | 8 +-- 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 PerfectNumbers.Core.Tests/MersenneDivisorCyclesGenerateGpuTests.cs diff --git a/PerfectNumbers.Core.Tests/MersenneDivisorCyclesGenerateGpuTests.cs b/PerfectNumbers.Core.Tests/MersenneDivisorCyclesGenerateGpuTests.cs new file mode 100644 index 0000000..f5dffd7 --- /dev/null +++ b/PerfectNumbers.Core.Tests/MersenneDivisorCyclesGenerateGpuTests.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.IO; +using FluentAssertions; +using PerfectNumbers.Core; +using Xunit; + +namespace PerfectNumbers.Core.Tests; + +public class MersenneDivisorCyclesGenerateGpuTests +{ + [Fact] + [Trait("Category", "Fast")] + public void GenerateGpu_produces_expected_cycles_for_small_range() + { + string path = Path.GetTempFileName(); + try + { + MersenneDivisorCycles.GenerateGpu(path, maxDivisor: 50UL, batchSize: 16, skipCount: 0, nextPosition: 0); + var pairs = new List<(ulong divisor, ulong cycle)>(); + using var stream = new FileStream(path, FileMode.Open, FileAccess.Read); + using var reader = new BinaryReader(stream); + while (stream.Position < stream.Length) + { + ulong d = reader.ReadUInt64(); + ulong c = reader.ReadUInt64(); + pairs.Add((d, c)); + } + + var expected = new List(); + for (ulong d = 3; d <= 50; d++) + { + if ((d & 1UL) == 0UL || d % 3UL == 0UL || d % 5UL == 0UL || d % 7UL == 0UL || d % 11UL == 0UL) + { + continue; + } + + expected.Add(d); + } + + pairs.Should().HaveCount(expected.Count); + foreach (var pair in pairs) + { + expected.Should().Contain(pair.divisor); + pair.cycle.Should().Be(MersenneDivisorCycles.CalculateCycleLength(pair.divisor)); + } + } + finally + { + if (File.Exists(path)) + { + File.Delete(path); + } + } + } +} diff --git a/PerfectNumbers.Core.Tests/MersenneNumberResidueGpuTesterTests.cs b/PerfectNumbers.Core.Tests/MersenneNumberResidueGpuTesterTests.cs index 307cffb..3aa2447 100644 --- a/PerfectNumbers.Core.Tests/MersenneNumberResidueGpuTesterTests.cs +++ b/PerfectNumbers.Core.Tests/MersenneNumberResidueGpuTesterTests.cs @@ -19,6 +19,7 @@ public class MersenneNumberResidueGpuTesterTests RunCase(tester, 23UL, 2UL, expectedPrime: false); RunCase(tester, 29UL, 37UL, expectedPrime: false); + RunCase(tester, 31UL, 1_000UL, expectedPrime: true); RunCase(tester, 89UL, 1_001UL, expectedPrime: true); RunCase(tester, 127UL, 1_001UL, expectedPrime: true); } diff --git a/PerfectNumbers.Core/MersenneDivisorCycles.cs b/PerfectNumbers.Core/MersenneDivisorCycles.cs index ad4aca0..d8dfc3f 100644 --- a/PerfectNumbers.Core/MersenneDivisorCycles.cs +++ b/PerfectNumbers.Core/MersenneDivisorCycles.cs @@ -280,10 +280,10 @@ public class MersenneDivisorCycles var bufferDiv = accelerator.Allocate1D(validDivisors); var bufferCycle = accelerator.Allocate1D(idx); - kernel( - count, - bufferDiv.View, - bufferCycle.View); + kernel( + idx, + bufferDiv.View, + bufferCycle.View); accelerator.Synchronize();