annotate src/fftw-3.3.8/kernel/primes.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents d0c2a83c1364
children
rev   line source
Chris@82 1 /*
Chris@82 2 * Copyright (c) 2003, 2007-14 Matteo Frigo
Chris@82 3 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
Chris@82 4 *
Chris@82 5 * This program is free software; you can redistribute it and/or modify
Chris@82 6 * it under the terms of the GNU General Public License as published by
Chris@82 7 * the Free Software Foundation; either version 2 of the License, or
Chris@82 8 * (at your option) any later version.
Chris@82 9 *
Chris@82 10 * This program is distributed in the hope that it will be useful,
Chris@82 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@82 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@82 13 * GNU General Public License for more details.
Chris@82 14 *
Chris@82 15 * You should have received a copy of the GNU General Public License
Chris@82 16 * along with this program; if not, write to the Free Software
Chris@82 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Chris@82 18 *
Chris@82 19 */
Chris@82 20
Chris@82 21
Chris@82 22 #include "kernel/ifftw.h"
Chris@82 23
Chris@82 24 /***************************************************************************/
Chris@82 25
Chris@82 26 /* Rader's algorithm requires lots of modular arithmetic, and if we
Chris@82 27 aren't careful we can have errors due to integer overflows. */
Chris@82 28
Chris@82 29 /* Compute (x * y) mod p, but watch out for integer overflows; we must
Chris@82 30 have 0 <= {x, y} < p.
Chris@82 31
Chris@82 32 If overflow is common, this routine is somewhat slower than
Chris@82 33 e.g. using 'long long' arithmetic. However, it has the advantage
Chris@82 34 of working when INT is 64 bits, and is also faster when overflow is
Chris@82 35 rare. FFTW calls this via the MULMOD macro, which further
Chris@82 36 optimizes for the case of small integers.
Chris@82 37 */
Chris@82 38
Chris@82 39 #define ADD_MOD(x, y, p) ((x) >= (p) - (y)) ? ((x) + ((y) - (p))) : ((x) + (y))
Chris@82 40
Chris@82 41 INT X(safe_mulmod)(INT x, INT y, INT p)
Chris@82 42 {
Chris@82 43 INT r;
Chris@82 44
Chris@82 45 if (y > x)
Chris@82 46 return X(safe_mulmod)(y, x, p);
Chris@82 47
Chris@82 48 A(0 <= y && x < p);
Chris@82 49
Chris@82 50 r = 0;
Chris@82 51 while (y) {
Chris@82 52 r = ADD_MOD(r, x*(y&1), p); y >>= 1;
Chris@82 53 x = ADD_MOD(x, x, p);
Chris@82 54 }
Chris@82 55
Chris@82 56 return r;
Chris@82 57 }
Chris@82 58
Chris@82 59 /***************************************************************************/
Chris@82 60
Chris@82 61 /* Compute n^m mod p, where m >= 0 and p > 0. If we really cared, we
Chris@82 62 could make this tail-recursive. */
Chris@82 63
Chris@82 64 INT X(power_mod)(INT n, INT m, INT p)
Chris@82 65 {
Chris@82 66 A(p > 0);
Chris@82 67 if (m == 0)
Chris@82 68 return 1;
Chris@82 69 else if (m % 2 == 0) {
Chris@82 70 INT x = X(power_mod)(n, m / 2, p);
Chris@82 71 return MULMOD(x, x, p);
Chris@82 72 }
Chris@82 73 else
Chris@82 74 return MULMOD(n, X(power_mod)(n, m - 1, p), p);
Chris@82 75 }
Chris@82 76
Chris@82 77 /* the following two routines were contributed by Greg Dionne. */
Chris@82 78 static INT get_prime_factors(INT n, INT *primef)
Chris@82 79 {
Chris@82 80 INT i;
Chris@82 81 INT size = 0;
Chris@82 82
Chris@82 83 A(n % 2 == 0); /* this routine is designed only for even n */
Chris@82 84 primef[size++] = (INT)2;
Chris@82 85 do {
Chris@82 86 n >>= 1;
Chris@82 87 } while ((n & 1) == 0);
Chris@82 88
Chris@82 89 if (n == 1)
Chris@82 90 return size;
Chris@82 91
Chris@82 92 for (i = 3; i * i <= n; i += 2)
Chris@82 93 if (!(n % i)) {
Chris@82 94 primef[size++] = i;
Chris@82 95 do {
Chris@82 96 n /= i;
Chris@82 97 } while (!(n % i));
Chris@82 98 }
Chris@82 99 if (n == 1)
Chris@82 100 return size;
Chris@82 101 primef[size++] = n;
Chris@82 102 return size;
Chris@82 103 }
Chris@82 104
Chris@82 105 INT X(find_generator)(INT p)
Chris@82 106 {
Chris@82 107 INT n, i, size;
Chris@82 108 INT primef[16]; /* smallest number = 32589158477190044730 > 2^64 */
Chris@82 109 INT pm1 = p - 1;
Chris@82 110
Chris@82 111 if (p == 2)
Chris@82 112 return 1;
Chris@82 113
Chris@82 114 size = get_prime_factors(pm1, primef);
Chris@82 115 n = 2;
Chris@82 116 for (i = 0; i < size; i++)
Chris@82 117 if (X(power_mod)(n, pm1 / primef[i], p) == 1) {
Chris@82 118 i = -1;
Chris@82 119 n++;
Chris@82 120 }
Chris@82 121 return n;
Chris@82 122 }
Chris@82 123
Chris@82 124 /* Return first prime divisor of n (It would be at best slightly faster to
Chris@82 125 search a static table of primes; there are 6542 primes < 2^16.) */
Chris@82 126 INT X(first_divisor)(INT n)
Chris@82 127 {
Chris@82 128 INT i;
Chris@82 129 if (n <= 1)
Chris@82 130 return n;
Chris@82 131 if (n % 2 == 0)
Chris@82 132 return 2;
Chris@82 133 for (i = 3; i*i <= n; i += 2)
Chris@82 134 if (n % i == 0)
Chris@82 135 return i;
Chris@82 136 return n;
Chris@82 137 }
Chris@82 138
Chris@82 139 int X(is_prime)(INT n)
Chris@82 140 {
Chris@82 141 return(n > 1 && X(first_divisor)(n) == n);
Chris@82 142 }
Chris@82 143
Chris@82 144 INT X(next_prime)(INT n)
Chris@82 145 {
Chris@82 146 while (!X(is_prime)(n)) ++n;
Chris@82 147 return n;
Chris@82 148 }
Chris@82 149
Chris@82 150 int X(factors_into)(INT n, const INT *primes)
Chris@82 151 {
Chris@82 152 for (; *primes != 0; ++primes)
Chris@82 153 while ((n % *primes) == 0)
Chris@82 154 n /= *primes;
Chris@82 155 return (n == 1);
Chris@82 156 }
Chris@82 157
Chris@82 158 /* integer square root. Return floor(sqrt(N)) */
Chris@82 159 INT X(isqrt)(INT n)
Chris@82 160 {
Chris@82 161 INT guess, iguess;
Chris@82 162
Chris@82 163 A(n >= 0);
Chris@82 164 if (n == 0) return 0;
Chris@82 165
Chris@82 166 guess = n; iguess = 1;
Chris@82 167
Chris@82 168 do {
Chris@82 169 guess = (guess + iguess) / 2;
Chris@82 170 iguess = n / guess;
Chris@82 171 } while (guess > iguess);
Chris@82 172
Chris@82 173 return guess;
Chris@82 174 }
Chris@82 175
Chris@82 176 static INT isqrt_maybe(INT n)
Chris@82 177 {
Chris@82 178 INT guess = X(isqrt)(n);
Chris@82 179 return guess * guess == n ? guess : 0;
Chris@82 180 }
Chris@82 181
Chris@82 182 #define divides(a, b) (((b) % (a)) == 0)
Chris@82 183 INT X(choose_radix)(INT r, INT n)
Chris@82 184 {
Chris@82 185 if (r > 0) {
Chris@82 186 if (divides(r, n)) return r;
Chris@82 187 return 0;
Chris@82 188 } else if (r == 0) {
Chris@82 189 return X(first_divisor)(n);
Chris@82 190 } else {
Chris@82 191 /* r is negative. If n = (-r) * q^2, take q as the radix */
Chris@82 192 r = 0 - r;
Chris@82 193 return (n > r && divides(r, n)) ? isqrt_maybe(n / r) : 0;
Chris@82 194 }
Chris@82 195 }
Chris@82 196
Chris@82 197 /* return A mod N, works for all A including A < 0 */
Chris@82 198 INT X(modulo)(INT a, INT n)
Chris@82 199 {
Chris@82 200 A(n > 0);
Chris@82 201 if (a >= 0)
Chris@82 202 return a % n;
Chris@82 203 else
Chris@82 204 return (n - 1) - ((-(a + (INT)1)) % n);
Chris@82 205 }
Chris@82 206
Chris@82 207 /* TRUE if N factors into small primes */
Chris@82 208 int X(factors_into_small_primes)(INT n)
Chris@82 209 {
Chris@82 210 static const INT primes[] = { 2, 3, 5, 0 };
Chris@82 211 return X(factors_into)(n, primes);
Chris@82 212 }