Skip to content

Commit f3d0034

Browse files
author
Oren (electricessence)
committed
Fixed issue with trial division "prime test".
1 parent 1ccfc65 commit f3d0034

File tree

2 files changed

+65
-18
lines changed

2 files changed

+65
-18
lines changed

source/TrialDivision.cs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ public static readonly ImmutableArray<ushort> FirstKnown
1313
= (new ushort[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541 })
1414
.ToImmutableArray();
1515

16+
static readonly ushort LastKnown = FirstKnown.Last();
17+
1618
public class U32 : PrimalityU32Base
1719
{
1820
public static readonly ImmutableArray<uint> FirstKnown32 = FirstKnown.Select(Convert.ToUInt32).ToImmutableArray();
@@ -30,28 +32,22 @@ public override ParallelQuery<uint> InParallel(in uint staringAt, ushort? degree
3032
return tests.Where(v => IsPrime(in v));
3133
}
3234

33-
// const ulong MAX_ULONG_SQUARE_ROOT = 4294967296;
34-
3535
protected override bool IsPrimeInternal(uint value)
3636
{
3737
var sqr = (uint)Math.Sqrt(value);
38-
39-
foreach (var p in AllNumbers())
38+
for (var p = 5U; p <= sqr; p += 2U)
4039
{
41-
if (value == p || p > sqr)
42-
return true;
43-
if (value % p == 0)
44-
return false;
40+
if (value % p == 0) return false;
4541
}
4642

47-
throw new Exception("Unexpectedly exited prime test loop.");
43+
return true;
4844
}
4945

5046
protected virtual IEnumerable<uint> AllNumbers()
5147
{
5248
var known = new LinkedList<uint>();
5349
var last = 0U;
54-
foreach (var k in FirstKnown32)
50+
foreach (var k in FirstKnown32) // precomputed
5551
{
5652
yield return k;
5753
last = k;
@@ -159,17 +155,14 @@ public override ParallelQuery<ulong> InParallel(in ulong staringAt, ushort? degr
159155

160156
protected override bool IsPrimeInternal(in ulong value)
161157
{
162-
var sqr = (ulong)Math.Sqrt(value);
163158

164-
foreach (var p in AllNumbers())
159+
var sqr = (ulong)Math.Sqrt(value);
160+
for (var p = 5UL; p <= sqr; p += 2UL)
165161
{
166-
if (value == p || p > sqr)
167-
return true;
168-
if (value % p == 0)
169-
return false;
162+
if (value % p == 0) return false;
170163
}
171164

172-
throw new Exception("Unexpectedly exited prime test loop.");
165+
return true;
173166
}
174167

175168
protected virtual IEnumerable<ulong> AllNumbers()

speed/Program.cs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,17 @@ internal class Program
1212

1313
static void Main()
1414
{
15+
Console.WriteLine("Singular Trial Division Tests:");
16+
17+
const uint test32 = 2130706433;
18+
Console.WriteLine("{0} U32 Benchmark", TrialDivBenchmark(test32));
19+
Console.WriteLine("{0} U32", TrialDiv(test32));
20+
const ulong test64 = 8592868089022906369;
21+
Console.WriteLine("{0} U64 Benchmark", TrialDivBenchmark(test64));
22+
Console.WriteLine("{0} U64", TrialDiv(test64));
23+
1524
Console.WriteLine();
25+
Console.WriteLine("Batch Tests:");
1626

1727
foreach (var s in Tests().OrderBy(t => t))
1828
Console.WriteLine(s);
@@ -38,8 +48,52 @@ static IEnumerable<string> Tests()
3848
yield return string.Format("{0} Optimized", Test<Optimized>(out _));
3949
}
4050

51+
static TimeSpan TrialDivBenchmark(uint value)
52+
{
53+
var sw = Stopwatch.StartNew();
54+
var max = Math.Sqrt(value);
55+
for (var i = 3U; i < max; i += 2U)
56+
{
57+
if (value % i == 0) throw new Exception("Is not prime.");
58+
}
59+
sw.Stop();
60+
return sw.Elapsed;
61+
}
62+
63+
static TimeSpan TrialDivBenchmark(ulong value)
64+
{
65+
var sw = Stopwatch.StartNew();
66+
var max = Math.Sqrt(value);
67+
for (var i = 3UL; i < max; i += 2UL)
68+
{
69+
if (value % i == 0) throw new Exception("Is not prime.");
70+
}
71+
sw.Stop();
72+
return sw.Elapsed;
73+
}
74+
75+
static TimeSpan TrialDiv(uint value)
76+
{
77+
var t = new TrialDivision.U32();
78+
t.IsPrime(value); // first run.
79+
var sw = Stopwatch.StartNew();
80+
if (!t.IsPrime(value)) throw new Exception("Is not prime.");
81+
sw.Stop();
82+
return sw.Elapsed;
83+
}
84+
85+
static TimeSpan TrialDiv(ulong value)
86+
{
87+
var t = new TrialDivision.U64();
88+
t.IsPrime(value); // first run.
89+
var sw = Stopwatch.StartNew();
90+
if (!t.IsPrime(value)) throw new Exception("Is not prime.");
91+
sw.Stop();
92+
return sw.Elapsed;
93+
}
94+
4195
static TimeSpan Test<T>(out List<uint> found, uint number = START_NUMBER_DEFAULT, uint times = TIMES_DEFAULT)
42-
where T : PrimalityBase<uint>, new()
96+
where T : PrimalityBase<uint>, new()
4397
{
4498
var sw = Stopwatch.StartNew();
4599
found = new List<uint>(PRIMES_TO_FIND);

0 commit comments

Comments
 (0)