xref: /minix3/crypto/external/bsd/heimdal/dist/lib/hcrypto/libtommath/etc/mersenne.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: mersenne.c,v 1.1.1.2 2014/04/24 12:45:39 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /* Finds Mersenne primes using the Lucas-Lehmer test
4ebfedea0SLionel Sambuc  *
5ebfedea0SLionel Sambuc  * Tom St Denis, tomstdenis@gmail.com
6ebfedea0SLionel Sambuc  */
7ebfedea0SLionel Sambuc #include <time.h>
8ebfedea0SLionel Sambuc #include <tommath.h>
9ebfedea0SLionel Sambuc 
10ebfedea0SLionel Sambuc int
is_mersenne(long s,int * pp)11ebfedea0SLionel Sambuc is_mersenne (long s, int *pp)
12ebfedea0SLionel Sambuc {
13ebfedea0SLionel Sambuc   mp_int  n, u;
14ebfedea0SLionel Sambuc   int     res, k;
15ebfedea0SLionel Sambuc 
16ebfedea0SLionel Sambuc   *pp = 0;
17ebfedea0SLionel Sambuc 
18ebfedea0SLionel Sambuc   if ((res = mp_init (&n)) != MP_OKAY) {
19ebfedea0SLionel Sambuc     return res;
20ebfedea0SLionel Sambuc   }
21ebfedea0SLionel Sambuc 
22ebfedea0SLionel Sambuc   if ((res = mp_init (&u)) != MP_OKAY) {
23ebfedea0SLionel Sambuc     goto LBL_N;
24ebfedea0SLionel Sambuc   }
25ebfedea0SLionel Sambuc 
26ebfedea0SLionel Sambuc   /* n = 2^s - 1 */
27ebfedea0SLionel Sambuc   if ((res = mp_2expt(&n, s)) != MP_OKAY) {
28ebfedea0SLionel Sambuc      goto LBL_MU;
29ebfedea0SLionel Sambuc   }
30ebfedea0SLionel Sambuc   if ((res = mp_sub_d (&n, 1, &n)) != MP_OKAY) {
31ebfedea0SLionel Sambuc     goto LBL_MU;
32ebfedea0SLionel Sambuc   }
33ebfedea0SLionel Sambuc 
34ebfedea0SLionel Sambuc   /* set u=4 */
35ebfedea0SLionel Sambuc   mp_set (&u, 4);
36ebfedea0SLionel Sambuc 
37ebfedea0SLionel Sambuc   /* for k=1 to s-2 do */
38ebfedea0SLionel Sambuc   for (k = 1; k <= s - 2; k++) {
39ebfedea0SLionel Sambuc     /* u = u^2 - 2 mod n */
40ebfedea0SLionel Sambuc     if ((res = mp_sqr (&u, &u)) != MP_OKAY) {
41ebfedea0SLionel Sambuc       goto LBL_MU;
42ebfedea0SLionel Sambuc     }
43ebfedea0SLionel Sambuc     if ((res = mp_sub_d (&u, 2, &u)) != MP_OKAY) {
44ebfedea0SLionel Sambuc       goto LBL_MU;
45ebfedea0SLionel Sambuc     }
46ebfedea0SLionel Sambuc 
47ebfedea0SLionel Sambuc     /* make sure u is positive */
48ebfedea0SLionel Sambuc     while (u.sign == MP_NEG) {
49ebfedea0SLionel Sambuc       if ((res = mp_add (&u, &n, &u)) != MP_OKAY) {
50ebfedea0SLionel Sambuc          goto LBL_MU;
51ebfedea0SLionel Sambuc       }
52ebfedea0SLionel Sambuc     }
53ebfedea0SLionel Sambuc 
54ebfedea0SLionel Sambuc     /* reduce */
55ebfedea0SLionel Sambuc     if ((res = mp_reduce_2k (&u, &n, 1)) != MP_OKAY) {
56ebfedea0SLionel Sambuc       goto LBL_MU;
57ebfedea0SLionel Sambuc     }
58ebfedea0SLionel Sambuc   }
59ebfedea0SLionel Sambuc 
60ebfedea0SLionel Sambuc   /* if u == 0 then its prime */
61ebfedea0SLionel Sambuc   if (mp_iszero (&u) == 1) {
62ebfedea0SLionel Sambuc     mp_prime_is_prime(&n, 8, pp);
63ebfedea0SLionel Sambuc   if (*pp != 1) printf("FAILURE\n");
64ebfedea0SLionel Sambuc   }
65ebfedea0SLionel Sambuc 
66ebfedea0SLionel Sambuc   res = MP_OKAY;
67ebfedea0SLionel Sambuc LBL_MU:mp_clear (&u);
68ebfedea0SLionel Sambuc LBL_N:mp_clear (&n);
69ebfedea0SLionel Sambuc   return res;
70ebfedea0SLionel Sambuc }
71ebfedea0SLionel Sambuc 
72ebfedea0SLionel Sambuc /* square root of a long < 65536 */
73ebfedea0SLionel Sambuc long
i_sqrt(long x)74ebfedea0SLionel Sambuc i_sqrt (long x)
75ebfedea0SLionel Sambuc {
76ebfedea0SLionel Sambuc   long    x1, x2;
77ebfedea0SLionel Sambuc 
78ebfedea0SLionel Sambuc   x2 = 16;
79ebfedea0SLionel Sambuc   do {
80ebfedea0SLionel Sambuc     x1 = x2;
81ebfedea0SLionel Sambuc     x2 = x1 - ((x1 * x1) - x) / (2 * x1);
82ebfedea0SLionel Sambuc   } while (x1 != x2);
83ebfedea0SLionel Sambuc 
84ebfedea0SLionel Sambuc   if (x1 * x1 > x) {
85ebfedea0SLionel Sambuc     --x1;
86ebfedea0SLionel Sambuc   }
87ebfedea0SLionel Sambuc 
88ebfedea0SLionel Sambuc   return x1;
89ebfedea0SLionel Sambuc }
90ebfedea0SLionel Sambuc 
91ebfedea0SLionel Sambuc /* is the long prime by brute force */
92ebfedea0SLionel Sambuc int
isprime(long k)93ebfedea0SLionel Sambuc isprime (long k)
94ebfedea0SLionel Sambuc {
95ebfedea0SLionel Sambuc   long    y, z;
96ebfedea0SLionel Sambuc 
97ebfedea0SLionel Sambuc   y = i_sqrt (k);
98ebfedea0SLionel Sambuc   for (z = 2; z <= y; z++) {
99ebfedea0SLionel Sambuc     if ((k % z) == 0)
100ebfedea0SLionel Sambuc       return 0;
101ebfedea0SLionel Sambuc   }
102ebfedea0SLionel Sambuc   return 1;
103ebfedea0SLionel Sambuc }
104ebfedea0SLionel Sambuc 
105ebfedea0SLionel Sambuc 
106ebfedea0SLionel Sambuc int
main(void)107ebfedea0SLionel Sambuc main (void)
108ebfedea0SLionel Sambuc {
109ebfedea0SLionel Sambuc   int     pp;
110ebfedea0SLionel Sambuc   long    k;
111ebfedea0SLionel Sambuc   clock_t tt;
112ebfedea0SLionel Sambuc 
113ebfedea0SLionel Sambuc   k = 3;
114ebfedea0SLionel Sambuc 
115ebfedea0SLionel Sambuc   for (;;) {
116ebfedea0SLionel Sambuc     /* start time */
117ebfedea0SLionel Sambuc     tt = clock ();
118ebfedea0SLionel Sambuc 
119ebfedea0SLionel Sambuc     /* test if 2^k - 1 is prime */
120ebfedea0SLionel Sambuc     if (is_mersenne (k, &pp) != MP_OKAY) {
121ebfedea0SLionel Sambuc       printf ("Whoa error\n");
122ebfedea0SLionel Sambuc       return -1;
123ebfedea0SLionel Sambuc     }
124ebfedea0SLionel Sambuc 
125ebfedea0SLionel Sambuc     if (pp == 1) {
126ebfedea0SLionel Sambuc       /* count time */
127ebfedea0SLionel Sambuc       tt = clock () - tt;
128ebfedea0SLionel Sambuc 
129ebfedea0SLionel Sambuc       /* display if prime */
130ebfedea0SLionel Sambuc       printf ("2^%-5ld - 1 is prime, test took %ld ticks\n", k, tt);
131ebfedea0SLionel Sambuc     }
132ebfedea0SLionel Sambuc 
133ebfedea0SLionel Sambuc     /* goto next odd exponent */
134ebfedea0SLionel Sambuc     k += 2;
135ebfedea0SLionel Sambuc 
136ebfedea0SLionel Sambuc     /* but make sure its prime */
137ebfedea0SLionel Sambuc     while (isprime (k) == 0) {
138ebfedea0SLionel Sambuc       k += 2;
139ebfedea0SLionel Sambuc     }
140ebfedea0SLionel Sambuc   }
141ebfedea0SLionel Sambuc   return 0;
142ebfedea0SLionel Sambuc }
143ebfedea0SLionel Sambuc 
144ebfedea0SLionel Sambuc /* Source: /cvs/libtom/libtommath/etc/mersenne.c,v  */
145ebfedea0SLionel Sambuc /* Revision: 1.3  */
146ebfedea0SLionel Sambuc /* Date: 2006/03/31 14:18:47  */
147