Skip to content

Commit e7d2a1f

Browse files
author
Oren (electricessence)
committed
Added prime numbers.
1 parent 8fa251a commit e7d2a1f

3 files changed

Lines changed: 338 additions & 13 deletions

File tree

Numeric.cs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
using System.Globalization;
88

99

10-
namespace Open.Formatting
10+
namespace Open.Numeric
1111
{
12-
public static class Numeric
12+
public static class Extensions
1313
{
1414
#region Numeric shortcuts.
1515
public static bool IsNaN(this double value)
@@ -237,17 +237,22 @@ public static double ToDouble(this float? value, int precision)
237237
return value.HasValue ? value.Value.ToDouble(precision) : double.NaN;
238238
}
239239

240-
/// <summary>
241-
/// Accurate way to convert possible float to double by converting to string first. Avoids tolerance issues.
242-
/// Uses default double convert if not a float.
243-
/// </summary>
244-
public static double ToDouble(object value)
245-
{
246-
if (value == null)
247-
return double.NaN;
248-
249-
return value is float ? ((float)value).ToDouble() : Convert.ToDouble(value);
250-
}
251240
#endregion
252241
}
242+
243+
public static class NumericConvert
244+
{
245+
246+
/// <summary>
247+
/// Accurate way to convert possible float to double by converting to string first. Avoids tolerance issues.
248+
/// Uses default double convert if not a float.
249+
/// </summary>
250+
public static double ToDouble(object value)
251+
{
252+
if (value == null)
253+
return double.NaN;
254+
255+
return value is float ? ((float)value).ToDouble() : Convert.ToDouble(value);
256+
}
257+
}
253258
}

Prime.cs

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace Open.Numeric.Primes
6+
{
7+
public static class Number
8+
{
9+
static bool IsPrimeInternal(ulong value)
10+
{
11+
if (value < 380000)
12+
{
13+
// This method is faster up until a point.
14+
double squared = Math.Sqrt(value);
15+
ulong flooredAndSquared = Convert.ToUInt64(Math.Floor(squared));
16+
17+
for (ulong idx = 3; idx <= flooredAndSquared; idx++)
18+
{
19+
if (value % idx == 0)
20+
{
21+
return false;
22+
}
23+
}
24+
}
25+
else
26+
{
27+
ulong divisor = 6;
28+
while (divisor * divisor - 2 * divisor + 1 <= value)
29+
{
30+
31+
if (value % (divisor - 1) == 0)
32+
return false;
33+
34+
if (value % (divisor + 1) == 0)
35+
return false;
36+
37+
divisor += 6;
38+
}
39+
}
40+
41+
42+
43+
return true;
44+
}
45+
46+
/// <summary>
47+
/// Validates if a number is prime.
48+
/// </summary>
49+
/// <param name="value">Value to verify.</param>
50+
/// <returns>True if the provided value is a prime number</returns>
51+
public static bool IsPrime(ulong value)
52+
{
53+
switch (value)
54+
{
55+
// 0 and 1 are not prime numbers
56+
case 0:
57+
case 1:
58+
return false;
59+
60+
case 2:
61+
case 3:
62+
return true;
63+
64+
default:
65+
return value % 2 != 0
66+
&& value % 3 != 0
67+
&& IsPrimeInternal(value);
68+
}
69+
70+
}
71+
72+
/// <summary>
73+
/// Validates if a number is prime.
74+
/// </summary>
75+
/// <param name="value">Value to verify.</param>
76+
/// <returns>True if the provided value is a prime number</returns>
77+
public static bool IsPrime(long value)
78+
{
79+
return IsPrime((ulong)Math.Abs(value));
80+
}
81+
82+
public static bool IsPrime(double value)
83+
{
84+
return (Math.Floor(value) == value)
85+
? IsPrime((long)value)
86+
: false;
87+
}
88+
89+
public static IEnumerable<ulong> MultiplesOf(ulong value)
90+
{
91+
ulong last = 1;
92+
93+
foreach (var p in Prime.Numbers())
94+
{
95+
ulong stop = value / last; // The list of possibilities shrinks for each test.
96+
if (p > stop) break; // Exceeded possibilities?
97+
while ((value % p) == 0)
98+
{
99+
value /= p;
100+
yield return p;
101+
if (value == 1) yield break;
102+
}
103+
last = p;
104+
}
105+
106+
yield return value;
107+
}
108+
}
109+
110+
public static class Prime
111+
{
112+
113+
internal static IEnumerable<ulong> ValidPrimeTests(ulong staringAt = 2)
114+
{
115+
if (staringAt > 2)
116+
{
117+
if (staringAt % 2 == 0)
118+
staringAt++;
119+
}
120+
{
121+
yield return 2;
122+
staringAt = 3;
123+
}
124+
125+
for (ulong n = staringAt; n < ulong.MaxValue - 1; n += 2)
126+
yield return n;
127+
}
128+
129+
internal static IEnumerable<long> ValidPrimeTests(long staringAt = 2)
130+
{
131+
var sign = staringAt < 0 ? -1 : 1;
132+
staringAt = Math.Abs(staringAt);
133+
134+
if (staringAt > 2)
135+
{
136+
if (staringAt % 2 == 0)
137+
staringAt++;
138+
}
139+
{
140+
yield return sign * 2;
141+
staringAt = 3;
142+
}
143+
144+
for (long n = staringAt; n < long.MaxValue - 1; n += 2)
145+
yield return sign * n;
146+
}
147+
148+
/// <summary>
149+
/// Returns an enumerable that will iterate every prime starting at the starting value.
150+
/// </summary>
151+
/// <param name="staringAt">Allows for skipping ahead any integer before checking for inclusive and subsequent primes.</param>
152+
/// <returns></returns>
153+
public static IEnumerable<ulong> Numbers(ulong staringAt = 2)
154+
{
155+
return ValidPrimeTests(staringAt)
156+
.Where(v => Number.IsPrime(v));
157+
}
158+
159+
/// <summary>
160+
/// Returns an enumerable that will iterate every prime starting at the starting value.
161+
/// </summary>
162+
/// <param name="staringAt">Allows for skipping ahead any integer before checking for inclusive and subsequent primes. Passing a negative number here will produce a negative set of prime numbers.</param>
163+
/// <returns></returns>
164+
public static IEnumerable<long> Numbers(long staringAt)
165+
{
166+
return ValidPrimeTests(staringAt)
167+
.Where(v => Number.IsPrime(v));
168+
}
169+
170+
/// <summary>
171+
/// Returns a parallel enumerable that will iterate every prime starting at the starting value.
172+
/// </summary>
173+
/// <param name="staringAt">Allows for skipping ahead any integer before checking for inclusive and subsequent primes.</param>
174+
/// <param name="degreeOfParallelism">Operates in parallel unless 1 is specified.</param>
175+
/// <returns></returns>
176+
public static ParallelQuery<ulong> NumbersInParallel(ulong staringAt = 2, ushort? degreeOfParallelism = null)
177+
{
178+
var tests = ValidPrimeTests(staringAt)
179+
.AsParallel().AsOrdered();
180+
181+
if (degreeOfParallelism.HasValue)
182+
tests = tests.WithDegreeOfParallelism(degreeOfParallelism.Value);
183+
184+
return tests.Where(v => Number.IsPrime(v));
185+
}
186+
187+
/// <summary>
188+
/// Finds the next prime number after the number given.
189+
/// </summary>
190+
/// <param name="after">The excluded lower boundary to start with.</param>
191+
/// <returns>The next prime after the number provided.</returns>
192+
public static ulong Next(ulong after)
193+
{
194+
return Numbers(after + 1).First();
195+
}
196+
197+
198+
/// <summary>
199+
/// Finds the next prime number after the number given.
200+
/// </summary>
201+
/// <param name="after">The excluded lower boundary to start with. If this number is negative, then the result will be the next greater magnitude value prime as negative number.</param>
202+
/// <returns>The next prime after the number provided.</returns>
203+
public static long Next(long after)
204+
{
205+
var sign = after < 0 ? -1 : 1;
206+
after = Math.Abs(after);
207+
return sign * Numbers(after + 1).First();
208+
}
209+
210+
/// <summary>
211+
/// Finds the next prime number after the number given.
212+
/// </summary>
213+
/// <param name="after">The excluded lower boundary to start with. If this number is negative, then the result will be the next greater magnitude value prime as negative number.</param>
214+
/// <returns>The next prime after the number provided.</returns>
215+
public static long Next(double value)
216+
{
217+
return Next((long)value);
218+
}
219+
220+
}
221+
222+
223+
namespace Extensions
224+
{
225+
public static class PrimeExtensions
226+
{
227+
public static bool IsPrime(this ulong value)
228+
{
229+
return Number.IsPrime(value);
230+
}
231+
public static bool IsPrime(this long value)
232+
{
233+
return Number.IsPrime(value);
234+
}
235+
public static bool IsPrime(this double value)
236+
{
237+
return Number.IsPrime(value);
238+
}
239+
public static ulong NextPrime(this ulong value)
240+
{
241+
return Prime.Next(value);
242+
}
243+
public static long NextPrime(this long value)
244+
{
245+
return Prime.Next(value);
246+
}
247+
public static long NextPrime(this double value)
248+
{
249+
return Prime.Next(value);
250+
}
251+
}
252+
}
253+
}
254+

ProcedureResult.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
2+
using System;
3+
using Open.Formatting;
4+
5+
namespace Open.Arithmetic
6+
{
7+
public struct ProcedureResult : IComparable<ProcedureResult>
8+
{
9+
public readonly int Count;
10+
public readonly double Sum;
11+
public readonly double Average;
12+
public ProcedureResult(double sum, int count)
13+
{
14+
Count = count;
15+
Sum = sum;
16+
Average = count == 0 ? double.NaN : sum / count;
17+
}
18+
19+
20+
public ProcedureResult Add(double value, int count = 1)
21+
{
22+
return new ProcedureResult(Sum + value, Count + count);
23+
}
24+
25+
public int CompareTo(ProcedureResult other)
26+
{
27+
var a = Average;
28+
var b = other.Average;
29+
if (a.IsNearEqual(b, 0.00000001) && a.ToString() == b.ToString()) return 0; // We hate precision issues. :( 1==1 dammit!
30+
if (a < b || double.IsNaN(a) && !double.IsNaN(b)) return -1;
31+
if (a > b || !double.IsNaN(a) && double.IsNaN(b)) return +1;
32+
if (Count < other.Count) return -1;
33+
if (Count > other.Count) return +1;
34+
return 0;
35+
}
36+
37+
public static ProcedureResult operator +(ProcedureResult a, ProcedureResult b)
38+
{
39+
return new ProcedureResult(
40+
a.Sum + b.Count,
41+
a.Count + b.Count
42+
);
43+
}
44+
45+
public static bool operator >(ProcedureResult a, ProcedureResult b)
46+
{
47+
return a.CompareTo(b) == 1;
48+
}
49+
50+
public static bool operator <(ProcedureResult a, ProcedureResult b)
51+
{
52+
return a.CompareTo(b) == -1;
53+
}
54+
55+
public static bool operator >=(ProcedureResult a, ProcedureResult b)
56+
{
57+
return a.CompareTo(b) >= 0;
58+
}
59+
60+
public static bool operator <=(ProcedureResult a, ProcedureResult b)
61+
{
62+
return a.CompareTo(b) <= 0;
63+
}
64+
65+
}
66+
}

0 commit comments

Comments
 (0)