prime.cs

View source code here on GitHub!

Includes

class Prime
static IEnumerable<T> Primes<T> (T? stop = null)

This function implements the Sieve of Eratosthenes. In general, it will iterate over all of the prime numbers. You can also provide an optional stop argument, which will force it to not yield any numbers above that limit. Below is a gif (courtesy of Wikipedia) that demonstrates the principle of the sieve.

Any animated example of the Sieve of Eratosthenes
static IEnumerable<T> PrimeFactors<T> (T n)

This function will iterate over all the prime factors of a number, as well as -1 and 0 if relevant.

static dynamic isComposite (Int64 n)

Returns 0 if the number is prime, and the smallest prime factor otherwise.

static Boolean isPrime (dynamic n)

Returns true if the number is prime, and false otherwise.

  1using System;
  2using System.Collections.Generic;
  3
  4namespace Euler
  5{
  6    public static class Prime
  7    {
  8        private static readonly Dictionary<Type, (dynamic LastCached, List<dynamic> Cache)> Caches = new();
  9
 10        public static IEnumerable<T> Primes<T>(T? stop = null) where T : struct
 11        {
 12            foreach (dynamic p in _Primes(stop))
 13                yield return (T)p;
 14        }
 15
 16        private static IEnumerable<dynamic> _Primes(dynamic? stop = null)
 17        {
 18            Type type = stop != null ? stop.GetType() : typeof(long);
 19            if (!Caches.TryGetValue(type, out var cacheData))
 20            {
 21                cacheData = (LastCached: (dynamic)0, Cache: new List<dynamic>());
 22                Caches[type] = cacheData;
 23            }
 24            (dynamic lastCached, List<dynamic> cache) = cacheData;
 25
 26            // Yield cached values
 27            if (stop == null)
 28                foreach (dynamic p in cache)
 29                    yield return p;
 30            else
 31                foreach (dynamic p in cache)
 32                    if (p < stop)
 33                        yield return p;
 34                    else
 35                        break;
 36
 37            // Generate new primes
 38            if (stop != null && lastCached > stop)
 39                yield break;
 40
 41            foreach (dynamic p in ModifiedEratosthenes())
 42            {
 43                if (p <= lastCached)
 44                    continue;
 45                if (stop != null && p > stop)
 46                    break;
 47
 48                cache.Add(p);
 49                lastCached = p;
 50                Caches[type] = (lastCached, cache);
 51                yield return p;
 52            }
 53        }
 54
 55        private static IEnumerable<dynamic> ModifiedEratosthenes()
 56        {
 57            yield return 2;
 58            yield return 3;
 59            yield return 5;
 60            yield return 7;
 61            var sieve = new Dictionary<dynamic, dynamic>();
 62            var recurse = ModifiedEratosthenes().GetEnumerator();
 63            recurse.MoveNext();
 64            recurse.MoveNext();
 65            dynamic prime = recurse.Current;
 66            if (prime != 3)
 67                throw new Exception();
 68            dynamic primeSquared = prime * prime;
 69            dynamic step = 2;
 70            for (dynamic candidate = 9; ; candidate += 2)
 71            {
 72                if (sieve.ContainsKey(candidate))
 73                {
 74                    step = sieve[candidate];
 75                    sieve.Remove(candidate);
 76                }
 77                else if (candidate < primeSquared)
 78                {
 79                    yield return candidate;
 80                    continue;
 81                }
 82                else
 83                {
 84                    step = prime * 2;
 85                    recurse.MoveNext();
 86                    prime = recurse.Current;
 87                    primeSquared = prime * prime;
 88                }
 89                dynamic tc = candidate;
 90                do
 91                {
 92                    tc += step;
 93                } while (sieve.ContainsKey(tc));
 94                sieve.Add(tc, step);
 95            }
 96        }
 97
 98        public static IEnumerable<T> PrimeFactors<T>(T n) where T : struct
 99        {
100            foreach (dynamic f in _PrimeFactors(n))
101                yield return (T)f;
102        }
103
104        private static IEnumerable<dynamic> _PrimeFactors(dynamic n)
105        {
106            if (n < 0)
107            {
108                yield return -1;
109                n = -n;
110            }
111            if (n == 0)
112                yield return 0;
113            else
114            {
115                dynamic root = (dynamic)Math.Ceiling(Math.Sqrt((double)n));
116                foreach (dynamic factor in _Primes())
117                {
118                    dynamic modulo = n % factor;
119                    if (modulo == 0)
120                    {
121                        do
122                        {
123                            yield return factor;
124                            n /= factor;
125                            modulo = n % factor;
126                        } while (modulo == 0);
127                        root = (dynamic)Math.Ceiling(Math.Sqrt((double)n));
128                    }
129                    if (n <= 1)
130                        break;
131                    if (factor > root)
132                    {
133                        yield return n;
134                        break;
135                    }
136                }
137            }
138        }
139
140        public static dynamic IsComposite(dynamic n)
141        {
142            var factors = PrimeFactors(n).GetEnumerator();
143            factors.MoveNext();
144            dynamic first = factors.Current;
145            if (first == n)
146                return 0;
147            return first;
148        }
149
150        public static bool IsPrime(dynamic n)
151        {
152            if (n < 2)
153                return false;
154            return IsComposite(n) == 0;
155        }
156    }
157}

Tags: csharp-iterator, prime-number