A (very) few UI improvements
[eigenmath-fx.git] / mprime.cpp
blob55086af46f28ab41ab4015463343ab3ce73e3ba4
1 // Bignum prime test (returns 1 if prime, 0 if not)
3 // Uses Algorithm P (probabilistic primality test) from p. 395 of
4 // "The Art of Computer Programming, Volume 2" by Donald E. Knuth.
6 #include "stdafx.h"
7 #include "defs.h"
9 static int mprimef(unsigned int *, unsigned int *, int);
11 int
12 mprime(unsigned int *n)
14 int i, k;
15 unsigned int *q;
17 // 1?
19 if (MLENGTH(n) == 1 && n[0] == 1)
20 return 0;
22 // 2?
24 if (MLENGTH(n) == 1 && n[0] == 2)
25 return 1;
27 // even?
29 if ((n[0] & 1) == 0)
30 return 0;
32 // n = 1 + (2 ^ k) q
34 q = mcopy(n);
36 k = 0;
37 do {
38 mshiftright(q);
39 k++;
40 } while ((q[0] & 1) == 0);
42 // try 25 times
44 for (i = 0; i < 25; i++)
45 if (mprimef(n, q, k) == 0)
46 break;
48 mfree(q);
50 if (i < 25)
51 return 0;
52 else
53 return 1;
56 //-----------------------------------------------------------------------------
58 // This is the actual implementation of Algorithm P.
60 // Input: n The number in question.
62 // q n = 1 + (2 ^ k) q
64 // k
66 // Output: 1 when n is probably prime
68 // 0 when n is definitely not prime
70 //-----------------------------------------------------------------------------
72 static int
73 mprimef(unsigned int *n, unsigned int *q, int k)
75 int i, j;
76 unsigned int *t, *x, *y;
78 // generate x
80 t = mcopy(n);
82 while (1) {
83 for (i = 0; i < MLENGTH(t); i++)
84 t[i] = rand();
85 x = mmod(t, n);
86 if (!MZERO(x) && !MEQUAL(x, 1))
87 break;
88 mfree(x);
91 mfree(t);
93 // exponentiate
95 y = mmodpow(x, q, n);
97 // done?
99 if (MEQUAL(y, 1)) {
100 mfree(x);
101 mfree(y);
102 return 1;
105 j = 0;
107 while (1) {
109 // y = n - 1?
111 t = msub(n, y);
113 if (MEQUAL(t, 1)) {
114 mfree(t);
115 mfree(x);
116 mfree(y);
117 return 1;
120 mfree(t);
122 if (++j == k) {
123 mfree(x);
124 mfree(y);
125 return 0;
128 // y = (y ^ 2) mod n
130 t = mmul(y, y);
131 mfree(y);
132 y = mmod(t, n);
133 mfree(t);
135 // y = 1?
137 if (MEQUAL(y, 1)) {
138 mfree(x);
139 mfree(y);
140 return 0;