xref: /netbsd-src/games/primes/spsp.c (revision 2429b427fa1a5cfbbfc02df7b1dd378c6d37214d)
1*2429b427Schristos /*	$NetBSD: spsp.c,v 1.2 2018/02/03 15:40:29 christos Exp $	*/
2bfe1fbfeSast 
3bfe1fbfeSast /*-
4bfe1fbfeSast  * Copyright (c) 2014 Colin Percival
5bfe1fbfeSast  * All rights reserved.
6bfe1fbfeSast  *
7bfe1fbfeSast  * Redistribution and use in source and binary forms, with or without
8bfe1fbfeSast  * modification, are permitted provided that the following conditions
9bfe1fbfeSast  * are met:
10bfe1fbfeSast  * 1. Redistributions of source code must retain the above copyright
11bfe1fbfeSast  *    notice, this list of conditions and the following disclaimer.
12bfe1fbfeSast  * 2. Redistributions in binary form must reproduce the above copyright
13bfe1fbfeSast  *    notice, this list of conditions and the following disclaimer in the
14bfe1fbfeSast  *    documentation and/or other materials provided with the distribution.
15bfe1fbfeSast  *
16bfe1fbfeSast  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17bfe1fbfeSast  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18bfe1fbfeSast  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19bfe1fbfeSast  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20bfe1fbfeSast  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21bfe1fbfeSast  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22bfe1fbfeSast  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23bfe1fbfeSast  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24bfe1fbfeSast  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25bfe1fbfeSast  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26bfe1fbfeSast  * SUCH DAMAGE.
27bfe1fbfeSast  */
28bfe1fbfeSast 
29bfe1fbfeSast #include <sys/cdefs.h>
30bfe1fbfeSast #ifndef lint
31bfe1fbfeSast __COPYRIGHT("@(#) Copyright (c) 1989, 1993\
32bfe1fbfeSast  The Regents of the University of California.  All rights reserved.");
33bfe1fbfeSast #endif /* not lint */
34bfe1fbfeSast 
35bfe1fbfeSast #ifndef lint
36bfe1fbfeSast #if 0
37bfe1fbfeSast static char sccsid[] = "@(#)primes.c    8.5 (Berkeley) 5/10/95";
38bfe1fbfeSast #else
39*2429b427Schristos __RCSID("$NetBSD: spsp.c,v 1.2 2018/02/03 15:40:29 christos Exp $");
40bfe1fbfeSast #endif
41bfe1fbfeSast #endif /* not lint */
42bfe1fbfeSast 
43bfe1fbfeSast #include <assert.h>
44bfe1fbfeSast #include <stddef.h>
45bfe1fbfeSast #include <stdint.h>
46bfe1fbfeSast 
47bfe1fbfeSast #include "primes.h"
48bfe1fbfeSast 
49*2429b427Schristos /* Return a * b % n, where 0 <= n. */
50bfe1fbfeSast static uint64_t
mulmod(uint64_t a,uint64_t b,uint64_t n)51bfe1fbfeSast mulmod(uint64_t a, uint64_t b, uint64_t n)
52bfe1fbfeSast {
53bfe1fbfeSast 	uint64_t x = 0;
54*2429b427Schristos 	uint64_t an = a % n;
55bfe1fbfeSast 
56bfe1fbfeSast 	while (b != 0) {
57*2429b427Schristos 		if (b & 1) {
58*2429b427Schristos 			x += an;
59*2429b427Schristos 			if ((x < an) || (x >= n))
60*2429b427Schristos 				x -= n;
61*2429b427Schristos 		}
62*2429b427Schristos 		if (an + an < an)
63*2429b427Schristos 			an = an + an - n;
64*2429b427Schristos 		else if (an + an >= n)
65*2429b427Schristos 			an = an + an - n;
66*2429b427Schristos 		else
67*2429b427Schristos 			an = an + an;
68*2429b427Schristos 
69bfe1fbfeSast 		b >>= 1;
70bfe1fbfeSast 	}
71bfe1fbfeSast 
72bfe1fbfeSast 	return (x);
73bfe1fbfeSast }
74bfe1fbfeSast 
75*2429b427Schristos /* Return a^r % n, where 0 < n. */
76bfe1fbfeSast static uint64_t
powmod(uint64_t a,uint64_t r,uint64_t n)77bfe1fbfeSast powmod(uint64_t a, uint64_t r, uint64_t n)
78bfe1fbfeSast {
79bfe1fbfeSast 	uint64_t x = 1;
80bfe1fbfeSast 
81bfe1fbfeSast 	while (r != 0) {
82bfe1fbfeSast 		if (r & 1)
83bfe1fbfeSast 			x = mulmod(a, x, n);
84bfe1fbfeSast 		a = mulmod(a, a, n);
85bfe1fbfeSast 		r >>= 1;
86bfe1fbfeSast 	}
87bfe1fbfeSast 
88bfe1fbfeSast 	return (x);
89bfe1fbfeSast }
90bfe1fbfeSast 
91bfe1fbfeSast /* Return non-zero if n is a strong pseudoprime to base p. */
92bfe1fbfeSast static int
spsp(uint64_t n,uint64_t p)93bfe1fbfeSast spsp(uint64_t n, uint64_t p)
94bfe1fbfeSast {
95bfe1fbfeSast 	uint64_t x;
96bfe1fbfeSast 	uint64_t r = n - 1;
97bfe1fbfeSast 	int k = 0;
98bfe1fbfeSast 
99bfe1fbfeSast 	/* Compute n - 1 = 2^k * r. */
100bfe1fbfeSast 	while ((r & 1) == 0) {
101bfe1fbfeSast 		k++;
102bfe1fbfeSast 		r >>= 1;
103bfe1fbfeSast 	}
104bfe1fbfeSast 
105bfe1fbfeSast 	/* Compute x = p^r mod n.  If x = 1, n is a p-spsp. */
106bfe1fbfeSast 	x = powmod(p, r, n);
107bfe1fbfeSast 	if (x == 1)
108bfe1fbfeSast 		return (1);
109bfe1fbfeSast 
110bfe1fbfeSast 	/* Compute x^(2^i) for 0 <= i < n.  If any are -1, n is a p-spsp. */
111bfe1fbfeSast 	while (k > 0) {
112bfe1fbfeSast 		if (x == n - 1)
113bfe1fbfeSast 			return (1);
114bfe1fbfeSast 		x = powmod(x, 2, n);
115bfe1fbfeSast 		k--;
116bfe1fbfeSast 	}
117bfe1fbfeSast 
118bfe1fbfeSast 	/* Not a p-spsp. */
119bfe1fbfeSast 	return (0);
120bfe1fbfeSast }
121bfe1fbfeSast 
122bfe1fbfeSast /* Test for primality using strong pseudoprime tests. */
123bfe1fbfeSast int
isprime(uint64_t _n)124bfe1fbfeSast isprime(uint64_t _n)
125bfe1fbfeSast {
126bfe1fbfeSast 	uint64_t n = _n;
127bfe1fbfeSast 
128bfe1fbfeSast 	/*
129bfe1fbfeSast 	 * Values from:
130bfe1fbfeSast 	 * C. Pomerance, J.L. Selfridge, and S.S. Wagstaff, Jr.,
131bfe1fbfeSast 	 * The pseudoprimes to 25 * 10^9, Math. Comp. 35(151):1003-1026, 1980.
132bfe1fbfeSast 	 */
133bfe1fbfeSast 
134bfe1fbfeSast 	/* No SPSPs to base 2 less than 2047. */
135bfe1fbfeSast 	if (!spsp(n, 2))
136bfe1fbfeSast 		return (0);
137bfe1fbfeSast 	if (n < 2047ULL)
138bfe1fbfeSast 		return (1);
139bfe1fbfeSast 
140bfe1fbfeSast 	/* No SPSPs to bases 2,3 less than 1373653. */
141bfe1fbfeSast 	if (!spsp(n, 3))
142bfe1fbfeSast 		return (0);
143bfe1fbfeSast 	if (n < 1373653ULL)
144bfe1fbfeSast 		return (1);
145bfe1fbfeSast 
146bfe1fbfeSast 	/* No SPSPs to bases 2,3,5 less than 25326001. */
147bfe1fbfeSast 	if (!spsp(n, 5))
148bfe1fbfeSast 		return (0);
149bfe1fbfeSast 	if (n < 25326001ULL)
150bfe1fbfeSast 		return (1);
151bfe1fbfeSast 
152bfe1fbfeSast 	/* No SPSPs to bases 2,3,5,7 less than 3215031751. */
153bfe1fbfeSast 	if (!spsp(n, 7))
154bfe1fbfeSast 		return (0);
155bfe1fbfeSast 	if (n < 3215031751ULL)
156bfe1fbfeSast 		return (1);
157bfe1fbfeSast 
158bfe1fbfeSast 	/*
159bfe1fbfeSast 	 * Values from:
160bfe1fbfeSast 	 * G. Jaeschke, On strong pseudoprimes to several bases,
161bfe1fbfeSast 	 * Math. Comp. 61(204):915-926, 1993.
162bfe1fbfeSast 	 */
163bfe1fbfeSast 
164bfe1fbfeSast 	/* No SPSPs to bases 2,3,5,7,11 less than 2152302898747. */
165bfe1fbfeSast 	if (!spsp(n, 11))
166bfe1fbfeSast 		return (0);
167bfe1fbfeSast 	if (n < 2152302898747ULL)
168bfe1fbfeSast 		return (1);
169bfe1fbfeSast 
170bfe1fbfeSast 	/* No SPSPs to bases 2,3,5,7,11,13 less than 3474749660383. */
171bfe1fbfeSast 	if (!spsp(n, 13))
172bfe1fbfeSast 		return (0);
173bfe1fbfeSast 	if (n < 3474749660383ULL)
174bfe1fbfeSast 		return (1);
175bfe1fbfeSast 
176bfe1fbfeSast 	/* No SPSPs to bases 2,3,5,7,11,13,17 less than 341550071728321. */
177bfe1fbfeSast 	if (!spsp(n, 17))
178bfe1fbfeSast 		return (0);
179bfe1fbfeSast 	if (n < 341550071728321ULL)
180bfe1fbfeSast 		return (1);
181bfe1fbfeSast 
182bfe1fbfeSast 	/* No SPSPs to bases 2,3,5,7,11,13,17,19 less than 341550071728321. */
183bfe1fbfeSast 	if (!spsp(n, 19))
184bfe1fbfeSast 		return (0);
185bfe1fbfeSast 	if (n < 341550071728321ULL)
186bfe1fbfeSast 		return (1);
187bfe1fbfeSast 
188bfe1fbfeSast 	/*
189bfe1fbfeSast 	 * Value from:
190bfe1fbfeSast 	 * Y. Jiang and Y. Deng, Strong pseudoprimes to the first eight prime
191bfe1fbfeSast 	 * bases, Math. Comp. 83(290):2915-2924, 2014.
192bfe1fbfeSast 	 */
193bfe1fbfeSast 
194bfe1fbfeSast 	/* No SPSPs to bases 2..23 less than 3825123056546413051. */
195bfe1fbfeSast 	if (!spsp(n, 23))
196bfe1fbfeSast 		return (0);
197bfe1fbfeSast 	if (n < 3825123056546413051)
198bfe1fbfeSast 		return (1);
199*2429b427Schristos 	/*
200*2429b427Schristos 	 * Value from:
201*2429b427Schristos 	 * J. Sorenson and J. Webster, Strong pseudoprimes to twelve prime
202*2429b427Schristos 	 * bases, Math. Comp. 86(304):985-1003, 2017.
203*2429b427Schristos 	 */
204bfe1fbfeSast 
205*2429b427Schristos        /* No SPSPs to bases 2..37 less than 318665857834031151167461. */
206*2429b427Schristos        if (!spsp(n, 29))
207bfe1fbfeSast                return (0);
208*2429b427Schristos        if (!spsp(n, 31))
209*2429b427Schristos                return (0);
210*2429b427Schristos        if (!spsp(n, 37))
211*2429b427Schristos                return (0);
212*2429b427Schristos 
213*2429b427Schristos        /* All 64-bit values are less than 318665857834031151167461. */
214*2429b427Schristos        return (1);
215bfe1fbfeSast }
216