1 /**
2     This module provides arrays of prime numbers that are available at compile-time.
3     Arrays are calculated as long as you need, using CTFE.
4 */
5 module ctprimes;
6 
7 import std.traits : isIntegral;
8 
9 /**
10     Construct an array of prime number using CTFE.
11     The length of the array is `length`, and the type is `T[length]`.
12 
13     Params:
14         length = Length of array
15         T = The type of the elements of the array
16 */
17 public template ctPrimes(size_t length, T = size_t) if (isIntegral!T && 0 < length)
18 {
19     enum T[length] ctPrimes = () {
20         T[] result = [];
21         T n = 2;
22         while (result.length < length)
23         {
24             bool isprime = () {
25                 foreach (i; 2 .. n)
26                 {
27                     if (n % i == 0)
28                         return false;
29                 }
30                 return true;
31             }();
32             if (isprime)
33                 result ~= n;
34             n++;
35         }
36         return result;
37     }();
38 }
39 
40 ///
41 @safe unittest
42 {
43     import std.random : uniform;
44 
45     auto runtimevalue = uniform(0, 5);
46     static assert(!__traits(compiles, {
47             ctPrimes!runtimevalue; // Error: variable runtimevalue cannot be read at compile time
48         }));
49 
50     static assert(__traits(compiles, {
51             auto a = ctPrimes!(5, byte);
52             auto b = ctPrimes!(5, ubyte);
53             auto c = ctPrimes!(5, short);
54             auto d = ctPrimes!(5, int);
55             auto e = ctPrimes!(5, long);
56         }));
57 
58     static assert(!__traits(compiles, {
59             auto a = ctPrimes!(5, bool);
60             auto b = ctPrimes!(5, char);
61             auto c = ctPrimes!(5, double);
62         }));
63 
64     auto primes1 = ctPrimes!(10);
65     static assert(is(typeof(primes1) == size_t[10]));
66     assert(primes1 == [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]);
67 
68     auto primes2 = ctPrimes!1;
69     assert(primes2 == [2]);
70 }
71 
72 /**
73     Construct an array of all prime numbers less than N, using CTFE.
74     The type of the array is `typeof(N)[]`.
75 
76     Params:
77         N = All elements of result are less than this value
78 */
79 public template ctPrimesLessThan(alias N) if (isIntegral!(typeof(N)))
80 {
81     enum typeof(N)[] ctPrimesLessThan = () {
82         typeof(N)[] result = [];
83         typeof(N) n = 2;
84         while (true)
85         {
86             if (N <= n)
87                 return result;
88             bool isprime = () {
89                 foreach (i; 2 .. n)
90                 {
91                     if (n % i == 0)
92                         return false;
93                 }
94                 return true;
95             }();
96             if (isprime)
97                 result ~= n;
98             n++;
99         }
100     }();
101 }
102 
103 @safe unittest
104 {
105     import std.random : uniform;
106 
107     auto runtimevalue = uniform(0, 5);
108     static assert(!__traits(compiles, {
109             ctPrimes!runtimevalue; // Error: variable runtimevalue cannot be read at compile time
110         }));
111 
112     static assert(__traits(compiles, {
113             auto a = ctPrimesLessThan!(cast(byte) 5);
114             auto b = ctPrimesLessThan!(cast(ubyte) 5);
115             auto c = ctPrimesLessThan!(cast(short) 5);
116             auto d = ctPrimesLessThan!(cast(int) 5);
117             auto e = ctPrimesLessThan!(cast(long) 5);
118         }));
119 
120     static assert(!__traits(compiles, {
121             auto a = ctPrimesLessThan!(true);
122             auto b = ctPrimesLessThan!('a');
123             auto c = ctPrimesLessThan!(5f);
124         }));
125 
126     auto primes1 = ctPrimesLessThan!(10);
127     static assert(is(typeof(primes1) == typeof([1])));
128     assert(primes1 == [2, 3, 5, 7]);
129 
130     auto primes2 = ctPrimesLessThan!2;
131     assert(primes2 == []);
132 
133     auto primes3 = ctPrimesLessThan!0;
134     assert(primes3 == []);
135 }