Add three-A-two-B combined divisor schedule
This commit is contained in:
1 parent
465b40bf35
commit
e8d163f595
2 files changed
+84
-9
No files matched your search
@@ -13,7 +13,7 @@ public class HeuristicCombinedPrimeTesterTests
|
|||||||
[InlineData((byte)1)]
|
[InlineData((byte)1)]
|
||||||
[InlineData((byte)7)]
|
[InlineData((byte)7)]
|
||||||
[InlineData((byte)9)]
|
[InlineData((byte)9)]
|
||||||
public void Enumerator_uses_three_a_one_b_schedule_by_default(byte lastDigit)
|
public void Enumerator_uses_three_a_two_b_schedule_by_default(byte lastDigit)
|
||||||
{
|
{
|
||||||
Span<HeuristicCombinedPrimeTester.HeuristicGroupBSequenceState> groupBState =
|
Span<HeuristicCombinedPrimeTester.HeuristicGroupBSequenceState> groupBState =
|
||||||
stackalloc HeuristicCombinedPrimeTester.HeuristicGroupBSequenceState[4];
|
stackalloc HeuristicCombinedPrimeTester.HeuristicGroupBSequenceState[4];
|
||||||
@@ -49,12 +49,53 @@ public class HeuristicCombinedPrimeTesterTests
|
|||||||
groupACandidate.Group.Should().NotBe(HeuristicCombinedPrimeTester.HeuristicDivisorGroup.GroupB);
|
groupACandidate.Group.Should().NotBe(HeuristicCombinedPrimeTester.HeuristicDivisorGroup.GroupB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
HeuristicCombinedPrimeTester.HeuristicDivisorCandidate groupBCandidate = results[index++];
|
HeuristicCombinedPrimeTester.HeuristicDivisorCandidate groupBCandidate = results[index++];
|
||||||
groupBCandidate.Value.Should().BeGreaterThan(13UL);
|
groupBCandidate.Value.Should().BeGreaterThan(13UL);
|
||||||
(groupBCandidate.Value % 10UL).Should().NotBe(3UL);
|
(groupBCandidate.Value % 10UL).Should().NotBe(3UL);
|
||||||
groupBCandidate.Group.Should().Be(HeuristicCombinedPrimeTester.HeuristicDivisorGroup.GroupB);
|
groupBCandidate.Group.Should().Be(HeuristicCombinedPrimeTester.HeuristicDivisorGroup.GroupB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[Trait("Category", "Fast")]
|
||||||
|
[InlineData((byte)1)]
|
||||||
|
[InlineData((byte)7)]
|
||||||
|
[InlineData((byte)9)]
|
||||||
|
public void Three_a_two_b_pattern_interleaves_three_group_a_values_before_two_group_b_values(byte lastDigit)
|
||||||
|
{
|
||||||
|
ReadOnlySpan<uint> combined = HeuristicCombinedPrimeTester.GetCombinedDivisors(
|
||||||
|
lastDigit,
|
||||||
|
HeuristicCombinedPrimeTester.CombinedDivisorPattern.ThreeATwoB);
|
||||||
|
|
||||||
|
combined.Length.Should().BeGreaterThan(28);
|
||||||
|
combined[0].Should().Be(3U);
|
||||||
|
combined[1].Should().Be(7U);
|
||||||
|
combined[2].Should().Be(11U);
|
||||||
|
combined[3].Should().Be(13U);
|
||||||
|
|
||||||
|
int index = 4;
|
||||||
|
const int segmentsToCheck = 4;
|
||||||
|
|
||||||
|
for (int segment = 0; segment < segmentsToCheck; segment++)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
uint groupAValue = combined[index++];
|
||||||
|
groupAValue.Should().BeGreaterThan(13U);
|
||||||
|
(groupAValue % 10U).Should().Be(3U);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
uint groupBValue = combined[index++];
|
||||||
|
groupBValue.Should().BeGreaterThan(13U);
|
||||||
|
(groupBValue % 10U).Should().NotBe(3U);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[Trait("Category", "Fast")]
|
[Trait("Category", "Fast")]
|
||||||
|
|||||||
@@ -39,6 +39,11 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
private static readonly Lazy<uint[]> CombinedDivisorsEnding7ThreeAOneB = new(() => BuildCombinedDivisors(7, CombinedDivisorPattern.ThreeAOneB), LazyThreadSafetyMode.ExecutionAndPublication);
|
private static readonly Lazy<uint[]> CombinedDivisorsEnding7ThreeAOneB = new(() => BuildCombinedDivisors(7, CombinedDivisorPattern.ThreeAOneB), LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
private static readonly Lazy<uint[]> CombinedDivisorsEnding9ThreeAOneB = new(() => BuildCombinedDivisors(9, CombinedDivisorPattern.ThreeAOneB), LazyThreadSafetyMode.ExecutionAndPublication);
|
private static readonly Lazy<uint[]> CombinedDivisorsEnding9ThreeAOneB = new(() => BuildCombinedDivisors(9, CombinedDivisorPattern.ThreeAOneB), LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
|
|
||||||
|
private static readonly Lazy<uint[]> CombinedDivisorsEnding1ThreeATwoB = new(() => BuildCombinedDivisors(1, CombinedDivisorPattern.ThreeATwoB), LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
|
private static readonly Lazy<uint[]> CombinedDivisorsEnding3ThreeATwoB = new(() => BuildCombinedDivisors(3, CombinedDivisorPattern.ThreeATwoB), LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
|
private static readonly Lazy<uint[]> CombinedDivisorsEnding7ThreeATwoB = new(() => BuildCombinedDivisors(7, CombinedDivisorPattern.ThreeATwoB), LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
|
private static readonly Lazy<uint[]> CombinedDivisorsEnding9ThreeATwoB = new(() => BuildCombinedDivisors(9, CombinedDivisorPattern.ThreeATwoB), LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
|
|
||||||
private static readonly ulong[] HeuristicSmallCycleSnapshot = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot();
|
private static readonly ulong[] HeuristicSmallCycleSnapshot = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot();
|
||||||
|
|
||||||
internal enum CombinedDivisorPattern : byte
|
internal enum CombinedDivisorPattern : byte
|
||||||
@@ -46,6 +51,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
TwoAOneB = 0,
|
TwoAOneB = 0,
|
||||||
OneAOneB = 1,
|
OneAOneB = 1,
|
||||||
ThreeAOneB = 2,
|
ThreeAOneB = 2,
|
||||||
|
ThreeATwoB = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum HeuristicDivisorGroup : byte
|
internal enum HeuristicDivisorGroup : byte
|
||||||
@@ -404,7 +410,7 @@ Cleanup:
|
|||||||
|
|
||||||
private static ReadOnlySpan<uint> GetCombinedDivisors(byte nMod10)
|
private static ReadOnlySpan<uint> GetCombinedDivisors(byte nMod10)
|
||||||
{
|
{
|
||||||
return GetCombinedDivisors(nMod10, CombinedDivisorPattern.ThreeAOneB);
|
return GetCombinedDivisors(nMod10, CombinedDivisorPattern.ThreeATwoB);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ReadOnlySpan<uint> GetCombinedDivisors(byte nMod10, CombinedDivisorPattern pattern)
|
internal static ReadOnlySpan<uint> GetCombinedDivisors(byte nMod10, CombinedDivisorPattern pattern)
|
||||||
@@ -435,6 +441,14 @@ Cleanup:
|
|||||||
9 => CombinedDivisorsEnding9ThreeAOneB.Value,
|
9 => CombinedDivisorsEnding9ThreeAOneB.Value,
|
||||||
_ => ReadOnlySpan<uint>.Empty,
|
_ => ReadOnlySpan<uint>.Empty,
|
||||||
},
|
},
|
||||||
|
CombinedDivisorPattern.ThreeATwoB => nMod10 switch
|
||||||
|
{
|
||||||
|
1 => CombinedDivisorsEnding1ThreeATwoB.Value,
|
||||||
|
3 => CombinedDivisorsEnding3ThreeATwoB.Value,
|
||||||
|
7 => CombinedDivisorsEnding7ThreeATwoB.Value,
|
||||||
|
9 => CombinedDivisorsEnding9ThreeATwoB.Value,
|
||||||
|
_ => ReadOnlySpan<uint>.Empty,
|
||||||
|
},
|
||||||
_ => ReadOnlySpan<uint>.Empty,
|
_ => ReadOnlySpan<uint>.Empty,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -454,13 +468,31 @@ Cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int groupBIndex = GetGroupBStartIndex(groupB);
|
int groupBIndex = GetGroupBStartIndex(groupB);
|
||||||
int groupAInterleaveCount = pattern switch
|
int groupAInterleaveCount;
|
||||||
|
int groupBInterleaveCount;
|
||||||
|
switch (pattern)
|
||||||
{
|
{
|
||||||
CombinedDivisorPattern.OneAOneB => 1,
|
case CombinedDivisorPattern.OneAOneB:
|
||||||
CombinedDivisorPattern.TwoAOneB => 2,
|
groupAInterleaveCount = 1;
|
||||||
CombinedDivisorPattern.ThreeAOneB => 3,
|
groupBInterleaveCount = 1;
|
||||||
_ => 2,
|
break;
|
||||||
};
|
case CombinedDivisorPattern.TwoAOneB:
|
||||||
|
groupAInterleaveCount = 2;
|
||||||
|
groupBInterleaveCount = 1;
|
||||||
|
break;
|
||||||
|
case CombinedDivisorPattern.ThreeAOneB:
|
||||||
|
groupAInterleaveCount = 3;
|
||||||
|
groupBInterleaveCount = 1;
|
||||||
|
break;
|
||||||
|
case CombinedDivisorPattern.ThreeATwoB:
|
||||||
|
groupAInterleaveCount = 3;
|
||||||
|
groupBInterleaveCount = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
groupAInterleaveCount = 2;
|
||||||
|
groupBInterleaveCount = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
while (groupAIndex < groupA.Length || groupBIndex < groupB.Length)
|
while (groupAIndex < groupA.Length || groupBIndex < groupB.Length)
|
||||||
{
|
{
|
||||||
@@ -472,10 +504,12 @@ Cleanup:
|
|||||||
addedA++;
|
addedA++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupBIndex < groupB.Length)
|
int addedB = 0;
|
||||||
|
while (addedB < groupBInterleaveCount && groupBIndex < groupB.Length)
|
||||||
{
|
{
|
||||||
combined.Add(groupB[groupBIndex]);
|
combined.Add(groupB[groupBIndex]);
|
||||||
groupBIndex++;
|
groupBIndex++;
|
||||||
|
addedB++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user