Skip to content

Commit 83c2424

Browse files
author
electricessence
committed
Extended to include other number types.
Including BigInteger.
1 parent e7d2a1f commit 83c2424

1 file changed

Lines changed: 127 additions & 16 deletions

File tree

Prime.cs

Lines changed: 127 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Numerics;
45

56
namespace Open.Numeric.Primes
67
{
@@ -43,6 +44,24 @@ static bool IsPrimeInternal(ulong value)
4344
return true;
4445
}
4546

47+
static bool IsPrimeInternal(BigInteger value)
48+
{
49+
BigInteger divisor = 6;
50+
while (divisor * divisor - 2 * divisor + 1 <= value)
51+
{
52+
53+
if (value % (divisor - 1) == 0)
54+
return false;
55+
56+
if (value % (divisor + 1) == 0)
57+
return false;
58+
59+
divisor += 6;
60+
}
61+
62+
return true;
63+
}
64+
4665
/// <summary>
4766
/// Validates if a number is prime.
4867
/// </summary>
@@ -69,6 +88,24 @@ public static bool IsPrime(ulong value)
6988

7089
}
7190

91+
/// <summary>
92+
/// Validates if a number is prime.
93+
/// </summary>
94+
/// <param name="value">Value to verify.</param>
95+
/// <returns>True if the provided value is a prime number</returns>
96+
public static bool IsPrime(BigInteger value)
97+
{
98+
value = BigInteger.Abs(value);
99+
if (value == 0 || value == 1)
100+
return false;
101+
if (value == 2 || value == 3)
102+
return true;
103+
104+
return value % 2 != 0
105+
&& value % 3 != 0
106+
&& IsPrimeInternal(value);
107+
}
108+
72109
/// <summary>
73110
/// Validates if a number is prime.
74111
/// </summary>
@@ -79,13 +116,28 @@ public static bool IsPrime(long value)
79116
return IsPrime((ulong)Math.Abs(value));
80117
}
81118

119+
/// <summary>
120+
/// Validates if a number is prime.
121+
/// </summary>
122+
/// <param name="value">Value to verify.</param>
123+
/// <returns>True if the provided value is a prime number</returns>
82124
public static bool IsPrime(double value)
83125
{
84-
return (Math.Floor(value) == value)
85-
? IsPrime((long)value)
86-
: false;
126+
if(Math.Floor(value) != value)
127+
return false;
128+
129+
value = Math.Abs(value);
130+
if(value<=ulong.MaxValue)
131+
return IsPrime((ulong)value);
132+
133+
return IsPrime((BigInteger)value);
87134
}
88135

136+
/// <summary>
137+
/// Iterates the prime multiples of the provided value.
138+
/// </summary>
139+
/// <param name="value">Value to verify.</param>
140+
/// <returns>An enumerable that contains the multiples of the provided value.</returns>
89141
public static IEnumerable<ulong> MultiplesOf(ulong value)
90142
{
91143
ulong last = 1;
@@ -112,39 +164,77 @@ public static class Prime
112164

113165
internal static IEnumerable<ulong> ValidPrimeTests(ulong staringAt = 2)
114166
{
115-
if (staringAt > 2)
167+
var n = staringAt;
168+
if (n > 2)
116169
{
117-
if (staringAt % 2 == 0)
118-
staringAt++;
170+
if (n % 2 == 0)
171+
n++;
119172
}
173+
else
120174
{
121175
yield return 2;
122-
staringAt = 3;
176+
n = 3;
123177
}
124178

125-
for (ulong n = staringAt; n < ulong.MaxValue - 1; n += 2)
179+
for (; n < ulong.MaxValue - 1; n += 2)
126180
yield return n;
127181
}
128182

129-
internal static IEnumerable<long> ValidPrimeTests(long staringAt = 2)
183+
internal static IEnumerable<long> ValidPrimeTests(long staringAt)
130184
{
131185
var sign = staringAt < 0 ? -1 : 1;
132-
staringAt = Math.Abs(staringAt);
186+
var n = Math.Abs(staringAt);
133187

134-
if (staringAt > 2)
188+
if (n > 2)
135189
{
136-
if (staringAt % 2 == 0)
137-
staringAt++;
190+
if (n % 2 == 0)
191+
n++;
138192
}
193+
else
139194
{
140195
yield return sign * 2;
141-
staringAt = 3;
196+
n = 3;
142197
}
143198

144-
for (long n = staringAt; n < long.MaxValue - 1; n += 2)
199+
for (; n < long.MaxValue - 1; n += 2)
145200
yield return sign * n;
146201
}
147202

203+
internal static IEnumerable<BigInteger> ValidPrimeTests(BigInteger staringAt)
204+
{
205+
var sign = staringAt.Sign;
206+
if(sign==0) sign = 1;
207+
var n = BigInteger.Abs(staringAt);
208+
209+
if (n > 2)
210+
{
211+
if (n % 2 == 0)
212+
n++;
213+
}
214+
else
215+
{
216+
yield return sign * 2;
217+
n = 3;
218+
}
219+
220+
while(true)
221+
{
222+
yield return sign * n;
223+
n += 2;
224+
}
225+
}
226+
227+
/// <summary>
228+
/// Returns an enumerable that will iterate every prime starting at the starting value.
229+
/// </summary>
230+
/// <param name="staringAt">Allows for skipping ahead any integer before checking for inclusive and subsequent primes.</param>
231+
/// <returns></returns>
232+
public static IEnumerable<BigInteger> Numbers(BigInteger staringAt)
233+
{
234+
return ValidPrimeTests(staringAt)
235+
.Where(v => Number.IsPrime(v));
236+
}
237+
148238
/// <summary>
149239
/// Returns an enumerable that will iterate every prime starting at the starting value.
150240
/// </summary>
@@ -184,6 +274,23 @@ public static ParallelQuery<ulong> NumbersInParallel(ulong staringAt = 2, ushort
184274
return tests.Where(v => Number.IsPrime(v));
185275
}
186276

277+
/// <summary>
278+
/// Returns a parallel enumerable that will iterate every prime starting at the starting value.
279+
/// </summary>
280+
/// <param name="staringAt">Allows for skipping ahead any integer before checking for inclusive and subsequent primes.</param>
281+
/// <param name="degreeOfParallelism">Operates in parallel unless 1 is specified.</param>
282+
/// <returns></returns>
283+
public static ParallelQuery<BigInteger> NumbersInParallel(BigInteger staringAt, ushort? degreeOfParallelism = null)
284+
{
285+
var tests = ValidPrimeTests(staringAt)
286+
.AsParallel().AsOrdered();
287+
288+
if (degreeOfParallelism.HasValue)
289+
tests = tests.WithDegreeOfParallelism(degreeOfParallelism.Value);
290+
291+
return tests.Where(v => Number.IsPrime(v));
292+
}
293+
187294
/// <summary>
188295
/// Finds the next prime number after the number given.
189296
/// </summary>
@@ -194,7 +301,6 @@ public static ulong Next(ulong after)
194301
return Numbers(after + 1).First();
195302
}
196303

197-
198304
/// <summary>
199305
/// Finds the next prime number after the number given.
200306
/// </summary>
@@ -236,6 +342,11 @@ public static bool IsPrime(this double value)
236342
{
237343
return Number.IsPrime(value);
238344
}
345+
public static bool IsPrime(this BigInteger value)
346+
{
347+
return Number.IsPrime(value);
348+
}
349+
239350
public static ulong NextPrime(this ulong value)
240351
{
241352
return Prime.Next(value);

0 commit comments

Comments
 (0)