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 }