1 module dkh.numeric.prime; 2 3 /// xの約数一覧を返す 4 T[] divisorList(T)(T x) { 5 import std.algorithm : sort; 6 T[] res; 7 for (T i = 1; i*i <= x; i++) { 8 if (x%i == 0) { 9 res ~= i; 10 if (i*i != x) res ~= x/i; 11 } 12 } 13 sort(res); 14 return res; 15 } 16 17 /// 18 unittest { 19 import std.range, std.algorithm; 20 assert(equal(divisorList(1), [1])); 21 assert(equal(divisorList(2), [1, 2])); 22 assert(equal(divisorList(4), [1, 2, 4])); 23 assert(equal(divisorList(24), [1, 2, 3, 4, 6, 8, 12, 24])); 24 } 25 26 /// xの素因数一覧を返す 27 T[] factorList(T)(T x) { 28 T[] res; 29 for (T i = 2; i*i <= x; i++) { 30 while (x % i == 0) { 31 res ~= i; 32 x /= i; 33 } 34 } 35 if (x > 1) res ~= x; 36 // res is sorted! 37 return res; 38 } 39 40 /// 41 unittest { 42 import std.range, std.algorithm; 43 assert(equal(factorList(1), new int[0])); 44 assert(equal(factorList(2), [2])); 45 assert(equal(factorList(4), [2, 2])); 46 assert(equal(factorList(24), [2, 2, 2, 3])); 47 } 48 49 import dkh.numeric.primitive; 50 51 /// Millar-Rabin Test 52 bool isPrime(ulong n) { 53 import dkh.int128; 54 if (n <= 1) return false; 55 if (n == 2) return true; 56 if (n % 2 == 0) return false; 57 ulong d = n-1; 58 while (d % 2 == 0) d /= 2; 59 ulong[] alist = [2,3,5,7,11,13,17,19,23,29,31,37]; 60 foreach (a; alist) { 61 if (n <= a) break; 62 ulong y = ulongPowMod(a, d, n); 63 ulong t = d; 64 while (t != n-1 && y != 1 && y != n-1) { 65 y = mul128(y, y).mod128(n); 66 t <<= 1; 67 } 68 if (y != n-1 && t % 2 == 0) { 69 return false; 70 } 71 } 72 return true; 73 } 74 75 /// 76 unittest { 77 assert(!isPrime(0)); 78 assert(!isPrime(1)); 79 assert(isPrime(2)); 80 assert(isPrime(10^^9 + 7)); 81 }