16ae1554aSColin Percival /*-
26ae1554aSColin Percival * Copyright (c) 2014 Colin Percival
36ae1554aSColin Percival * All rights reserved.
46ae1554aSColin Percival *
56ae1554aSColin Percival * Redistribution and use in source and binary forms, with or without
66ae1554aSColin Percival * modification, are permitted provided that the following conditions
76ae1554aSColin Percival * are met:
86ae1554aSColin Percival * 1. Redistributions of source code must retain the above copyright
96ae1554aSColin Percival * notice, this list of conditions and the following disclaimer.
106ae1554aSColin Percival * 2. Redistributions in binary form must reproduce the above copyright
116ae1554aSColin Percival * notice, this list of conditions and the following disclaimer in the
126ae1554aSColin Percival * documentation and/or other materials provided with the distribution.
136ae1554aSColin Percival *
146ae1554aSColin Percival * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
156ae1554aSColin Percival * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166ae1554aSColin Percival * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
176ae1554aSColin Percival * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
186ae1554aSColin Percival * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
196ae1554aSColin Percival * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
206ae1554aSColin Percival * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
216ae1554aSColin Percival * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
226ae1554aSColin Percival * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
236ae1554aSColin Percival * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
246ae1554aSColin Percival * SUCH DAMAGE.
256ae1554aSColin Percival */
266ae1554aSColin Percival #include <sys/cdefs.h>
276ae1554aSColin Percival #include <stddef.h>
286ae1554aSColin Percival #include <stdint.h>
296ae1554aSColin Percival
306ae1554aSColin Percival #include "primes.h"
316ae1554aSColin Percival
32*ade8bceeSColin Percival /* Return a * b % n, where 0 < n. */
336ae1554aSColin Percival static uint64_t
mulmod(uint64_t a,uint64_t b,uint64_t n)346ae1554aSColin Percival mulmod(uint64_t a, uint64_t b, uint64_t n)
356ae1554aSColin Percival {
366ae1554aSColin Percival uint64_t x = 0;
37*ade8bceeSColin Percival uint64_t an = a % n;
386ae1554aSColin Percival
396ae1554aSColin Percival while (b != 0) {
40*ade8bceeSColin Percival if (b & 1) {
41*ade8bceeSColin Percival x += an;
42*ade8bceeSColin Percival if ((x < an) || (x >= n))
43*ade8bceeSColin Percival x -= n;
44*ade8bceeSColin Percival }
45*ade8bceeSColin Percival if (an + an < an)
46*ade8bceeSColin Percival an = an + an - n;
47*ade8bceeSColin Percival else if (an + an >= n)
48*ade8bceeSColin Percival an = an + an - n;
49*ade8bceeSColin Percival else
50*ade8bceeSColin Percival an = an + an;
516ae1554aSColin Percival b >>= 1;
526ae1554aSColin Percival }
536ae1554aSColin Percival
546ae1554aSColin Percival return (x);
556ae1554aSColin Percival }
566ae1554aSColin Percival
57*ade8bceeSColin Percival /* Return a^r % n, where 0 < n. */
586ae1554aSColin Percival static uint64_t
powmod(uint64_t a,uint64_t r,uint64_t n)596ae1554aSColin Percival powmod(uint64_t a, uint64_t r, uint64_t n)
606ae1554aSColin Percival {
616ae1554aSColin Percival uint64_t x = 1;
626ae1554aSColin Percival
636ae1554aSColin Percival while (r != 0) {
646ae1554aSColin Percival if (r & 1)
656ae1554aSColin Percival x = mulmod(a, x, n);
666ae1554aSColin Percival a = mulmod(a, a, n);
676ae1554aSColin Percival r >>= 1;
686ae1554aSColin Percival }
696ae1554aSColin Percival
706ae1554aSColin Percival return (x);
716ae1554aSColin Percival }
726ae1554aSColin Percival
736ae1554aSColin Percival /* Return non-zero if n is a strong pseudoprime to base p. */
746ae1554aSColin Percival static int
spsp(uint64_t n,uint64_t p)756ae1554aSColin Percival spsp(uint64_t n, uint64_t p)
766ae1554aSColin Percival {
776ae1554aSColin Percival uint64_t x;
786ae1554aSColin Percival uint64_t r = n - 1;
796ae1554aSColin Percival int k = 0;
806ae1554aSColin Percival
816ae1554aSColin Percival /* Compute n - 1 = 2^k * r. */
826ae1554aSColin Percival while ((r & 1) == 0) {
836ae1554aSColin Percival k++;
846ae1554aSColin Percival r >>= 1;
856ae1554aSColin Percival }
866ae1554aSColin Percival
876ae1554aSColin Percival /* Compute x = p^r mod n. If x = 1, n is a p-spsp. */
886ae1554aSColin Percival x = powmod(p, r, n);
896ae1554aSColin Percival if (x == 1)
906ae1554aSColin Percival return (1);
916ae1554aSColin Percival
926ae1554aSColin Percival /* Compute x^(2^i) for 0 <= i < n. If any are -1, n is a p-spsp. */
936ae1554aSColin Percival while (k > 0) {
946ae1554aSColin Percival if (x == n - 1)
956ae1554aSColin Percival return (1);
966ae1554aSColin Percival x = powmod(x, 2, n);
976ae1554aSColin Percival k--;
986ae1554aSColin Percival }
996ae1554aSColin Percival
1006ae1554aSColin Percival /* Not a p-spsp. */
1016ae1554aSColin Percival return (0);
1026ae1554aSColin Percival }
1036ae1554aSColin Percival
1046ae1554aSColin Percival /* Test for primality using strong pseudoprime tests. */
1056ae1554aSColin Percival int
isprime(ubig _n)1066ae1554aSColin Percival isprime(ubig _n)
1076ae1554aSColin Percival {
1086ae1554aSColin Percival uint64_t n = _n;
1096ae1554aSColin Percival
1106ae1554aSColin Percival /*
1116ae1554aSColin Percival * Values from:
1126ae1554aSColin Percival * C. Pomerance, J.L. Selfridge, and S.S. Wagstaff, Jr.,
1136ae1554aSColin Percival * The pseudoprimes to 25 * 10^9, Math. Comp. 35(151):1003-1026, 1980.
1146ae1554aSColin Percival */
1156ae1554aSColin Percival
1166ae1554aSColin Percival /* No SPSPs to base 2 less than 2047. */
1176ae1554aSColin Percival if (!spsp(n, 2))
1186ae1554aSColin Percival return (0);
1196ae1554aSColin Percival if (n < 2047ULL)
1206ae1554aSColin Percival return (1);
1216ae1554aSColin Percival
1226ae1554aSColin Percival /* No SPSPs to bases 2,3 less than 1373653. */
1236ae1554aSColin Percival if (!spsp(n, 3))
1246ae1554aSColin Percival return (0);
1256ae1554aSColin Percival if (n < 1373653ULL)
1266ae1554aSColin Percival return (1);
1276ae1554aSColin Percival
1286ae1554aSColin Percival /* No SPSPs to bases 2,3,5 less than 25326001. */
1296ae1554aSColin Percival if (!spsp(n, 5))
1306ae1554aSColin Percival return (0);
1316ae1554aSColin Percival if (n < 25326001ULL)
1326ae1554aSColin Percival return (1);
1336ae1554aSColin Percival
1346ae1554aSColin Percival /* No SPSPs to bases 2,3,5,7 less than 3215031751. */
1356ae1554aSColin Percival if (!spsp(n, 7))
1366ae1554aSColin Percival return (0);
1376ae1554aSColin Percival if (n < 3215031751ULL)
1386ae1554aSColin Percival return (1);
1396ae1554aSColin Percival
1406ae1554aSColin Percival /*
1416ae1554aSColin Percival * Values from:
1426ae1554aSColin Percival * G. Jaeschke, On strong pseudoprimes to several bases,
1436ae1554aSColin Percival * Math. Comp. 61(204):915-926, 1993.
1446ae1554aSColin Percival */
1456ae1554aSColin Percival
1466ae1554aSColin Percival /* No SPSPs to bases 2,3,5,7,11 less than 2152302898747. */
1476ae1554aSColin Percival if (!spsp(n, 11))
1486ae1554aSColin Percival return (0);
1496ae1554aSColin Percival if (n < 2152302898747ULL)
1506ae1554aSColin Percival return (1);
1516ae1554aSColin Percival
1526ae1554aSColin Percival /* No SPSPs to bases 2,3,5,7,11,13 less than 3474749660383. */
1536ae1554aSColin Percival if (!spsp(n, 13))
1546ae1554aSColin Percival return (0);
1556ae1554aSColin Percival if (n < 3474749660383ULL)
1566ae1554aSColin Percival return (1);
1576ae1554aSColin Percival
1586ae1554aSColin Percival /* No SPSPs to bases 2,3,5,7,11,13,17 less than 341550071728321. */
1596ae1554aSColin Percival if (!spsp(n, 17))
1606ae1554aSColin Percival return (0);
1616ae1554aSColin Percival if (n < 341550071728321ULL)
1626ae1554aSColin Percival return (1);
1636ae1554aSColin Percival
1646ae1554aSColin Percival /* No SPSPs to bases 2,3,5,7,11,13,17,19 less than 341550071728321. */
1656ae1554aSColin Percival if (!spsp(n, 19))
1666ae1554aSColin Percival return (0);
1676ae1554aSColin Percival if (n < 341550071728321ULL)
1686ae1554aSColin Percival return (1);
1696ae1554aSColin Percival
1706ae1554aSColin Percival /*
1716ae1554aSColin Percival * Value from:
1726ae1554aSColin Percival * Y. Jiang and Y. Deng, Strong pseudoprimes to the first eight prime
1736ae1554aSColin Percival * bases, Math. Comp. 83(290):2915-2924, 2014.
1746ae1554aSColin Percival */
1756ae1554aSColin Percival
1766ae1554aSColin Percival /* No SPSPs to bases 2..23 less than 3825123056546413051. */
1776ae1554aSColin Percival if (!spsp(n, 23))
1786ae1554aSColin Percival return (0);
1796ae1554aSColin Percival if (n < 3825123056546413051)
1806ae1554aSColin Percival return (1);
1816ae1554aSColin Percival
182*ade8bceeSColin Percival /*
183*ade8bceeSColin Percival * Value from:
184*ade8bceeSColin Percival * J. Sorenson and J. Webster, Strong pseudoprimes to twelve prime
185*ade8bceeSColin Percival * bases, Math. Comp. 86(304):985-1003, 2017.
186*ade8bceeSColin Percival */
1876ae1554aSColin Percival
188*ade8bceeSColin Percival /* No SPSPs to bases 2..37 less than 318665857834031151167461. */
189*ade8bceeSColin Percival if (!spsp(n, 29))
1906ae1554aSColin Percival return (0);
191*ade8bceeSColin Percival if (!spsp(n, 31))
192*ade8bceeSColin Percival return (0);
193*ade8bceeSColin Percival if (!spsp(n, 37))
194*ade8bceeSColin Percival return (0);
195*ade8bceeSColin Percival
196*ade8bceeSColin Percival /* All 64-bit values are less than 318665857834031151167461. */
197*ade8bceeSColin Percival return (1);
1986ae1554aSColin Percival }
199