github.com/cznic/mathutil@v0.0.0-20181122101859-297441e03548/mersenne/mersenne.go (about) 1 // Copyright (c) 2014 The mersenne Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 Package mersenne collects utilities related to Mersenne numbers[1] and/or some 7 of their properties. 8 9 Exponent 10 11 In this documentation the term 'exponent' refers to 'n' of a Mersenne number Mn 12 equal to 2^n-1. This package supports only uint32 sized exponents. New() 13 currently supports exponents only up to math.MaxInt32 (31 bits, up to 256 MB 14 required to represent such Mn in memory as a big.Int). 15 16 Links 17 18 Referenced from above: 19 [1] http://en.wikipedia.org/wiki/Mersenne_number 20 */ 21 package mersenne 22 23 import ( 24 "math" 25 "math/big" 26 27 "github.com/cznic/mathutil" 28 "github.com/remyoudompheng/bigfft" 29 ) 30 31 var ( 32 _0 = big.NewInt(0) 33 _1 = big.NewInt(1) 34 _2 = big.NewInt(2) 35 ) 36 37 // Knowns list the exponent of currently (March 2012) known Mersenne primes 38 // exponents in order. See also: http://oeis.org/A000043 for a partial list. 39 var Knowns = []uint32{ 40 2, // #1 41 3, // #2 42 5, // #3 43 7, // #4 44 13, // #5 45 17, // #6 46 19, // #7 47 31, // #8 48 61, // #9 49 89, // #10 50 51 107, // #11 52 127, // #12 53 521, // #13 54 607, // #14 55 1279, // #15 56 2203, // #16 57 2281, // #17 58 3217, // #18 59 4253, // #19 60 4423, // #20 61 62 9689, // #21 63 9941, // #22 64 11213, // #23 65 19937, // #24 66 21701, // #25 67 23209, // #26 68 44497, // #27 69 86243, // #28 70 110503, // #29 71 132049, // #30 72 73 216091, // #31 74 756839, // #32 75 859433, // #33 76 1257787, // #34 77 1398269, // #35 78 2976221, // #36 79 3021377, // #37 80 6972593, // #38 81 13466917, // #39 82 20996011, // #40 83 84 24036583, // #41 85 25964951, // #42 86 30402457, // #43 87 32582657, // #44 88 37156667, // #45 89 42643801, // #46 90 43112609, // #47 91 57885161, // #48 92 74207281, // #49 93 77232917, // #50 94 } 95 96 // Known maps the exponent of known Mersenne primes its ordinal number/rank. 97 // Ranks > 45 are currently provisional. 98 var Known map[uint32]int 99 100 func init() { 101 Known = map[uint32]int{} 102 for i, v := range Knowns { 103 Known[v] = i + 1 104 } 105 } 106 107 // New returns Mn == 2^n-1 for n <= math.MaxInt32 or nil otherwise. 108 func New(n uint32) (m *big.Int) { 109 if n > math.MaxInt32 { 110 return 111 } 112 113 m = big.NewInt(0) 114 return m.Sub(m.SetBit(m, int(n), 1), _1) 115 } 116 117 // HasFactorUint32 returns true if d | Mn. Typical run time for a 32 bit factor 118 // and a 32 bit exponent is < 1 µs. 119 func HasFactorUint32(d, n uint32) bool { 120 return d == 1 || d&1 != 0 && mathutil.ModPowUint32(2, n, d) == 1 121 } 122 123 // HasFactorUint64 returns true if d | Mn. Typical run time for a 64 bit factor 124 // and a 32 bit exponent is < 30 µs. 125 func HasFactorUint64(d uint64, n uint32) bool { 126 return d == 1 || d&1 != 0 && mathutil.ModPowUint64(2, uint64(n), d) == 1 127 } 128 129 // HasFactorBigInt returns true if d | Mn, d > 0. Typical run time for a 128 130 // bit factor and a 32 bit exponent is < 75 µs. 131 func HasFactorBigInt(d *big.Int, n uint32) bool { 132 return d.Cmp(_1) == 0 || d.Sign() > 0 && d.Bit(0) == 1 && 133 mathutil.ModPowBigInt(_2, big.NewInt(int64(n)), d).Cmp(_1) == 0 134 } 135 136 // HasFactorBigInt2 returns true if d | Mn, d > 0 137 func HasFactorBigInt2(d, n *big.Int) bool { 138 return d.Cmp(_1) == 0 || d.Sign() > 0 && d.Bit(0) == 1 && 139 mathutil.ModPowBigInt(_2, n, d).Cmp(_1) == 0 140 } 141 142 /* 143 FromFactorBigInt returns n such that d | Mn if n <= max and d is odd. In other 144 cases zero is returned. 145 146 It is conjectured that every odd d ∊ N divides infinitely many Mersenne numbers. 147 The returned n should be the exponent of smallest such Mn. 148 149 NOTE: The computation of n from a given d performs roughly in O(n). It is 150 thus highly recommended to use the 'max' argument to limit the "searched" 151 exponent upper bound as appropriate. Otherwise the computation can take a long 152 time as a large factor can be a divisor of a Mn with exponent above the uint32 153 limits. 154 155 The FromFactorBigInt function is a modification of the original Will 156 Edgington's "reverse method", discussed here: 157 http://tech.groups.yahoo.com/group/primenumbers/message/15061 158 */ 159 func FromFactorBigInt(d *big.Int, max uint32) (n uint32) { 160 if d.Bit(0) == 0 { 161 return 162 } 163 164 var m big.Int 165 for n < max { 166 m.Add(&m, d) 167 i := 0 168 for ; m.Bit(i) == 1; i++ { 169 if n == math.MaxUint32 { 170 return 0 171 } 172 173 n++ 174 } 175 m.Rsh(&m, uint(i)) 176 if m.Sign() == 0 { 177 if n > max { 178 n = 0 179 } 180 return 181 } 182 } 183 return 0 184 } 185 186 // Mod sets mod to n % Mexp and returns mod. It panics for exp == 0 || exp >= 187 // math.MaxInt32 || n < 0. 188 func Mod(mod, n *big.Int, exp uint32) *big.Int { 189 if exp == 0 || exp >= math.MaxInt32 || n.Sign() < 0 { 190 panic(0) 191 } 192 193 m := New(exp) 194 mod.Set(n) 195 var x big.Int 196 for mod.BitLen() > int(exp) { 197 x.Set(mod) 198 x.Rsh(&x, uint(exp)) 199 mod.And(mod, m) 200 mod.Add(mod, &x) 201 } 202 if mod.BitLen() == int(exp) && mod.Cmp(m) == 0 { 203 mod.SetInt64(0) 204 } 205 return mod 206 } 207 208 // ModPow2 returns x such that 2^Me % Mm == 2^x. It panics for m < 2. Typical 209 // run time is < 1 µs. Use instead of ModPow(2, e, m) wherever possible. 210 func ModPow2(e, m uint32) (x uint32) { 211 /* 212 m < 2 -> panic 213 e == 0 -> x == 0 214 e == 1 -> x == 1 215 216 2^M1 % M2 == 2^1 % 3 == 2^1 10 // 2^1, 3, 5, 7 ... +2k 217 2^M1 % M3 == 2^1 % 7 == 2^1 010 // 2^1, 4, 7, ... +3k 218 2^M1 % M4 == 2^1 % 15 == 2^1 0010 // 2^1, 5, 9, 13... +4k 219 2^M1 % M5 == 2^1 % 31 == 2^1 00010 // 2^1, 6, 11, 16... +5k 220 221 2^M2 % M2 == 2^3 % 3 == 2^1 10.. // 2^3, 5, 7, 9, 11, ... +2k 222 2^M2 % M3 == 2^3 % 7 == 2^0 001... // 2^3, 6, 9, 12, 15, ... +3k 223 2^M2 % M4 == 2^3 % 15 == 2^3 1000 // 2^3, 7, 11, 15, 19, ... +4k 224 2^M2 % M5 == 2^3 % 31 == 2^3 01000 // 2^3, 8, 13, 18, 23, ... +5k 225 226 2^M3 % M2 == 2^7 % 3 == 2^1 10..--.. // 2^3, 5, 7... +2k 227 2^M3 % M3 == 2^7 % 7 == 2^1 010...--- // 2^1, 4, 7... +3k 228 2^M3 % M4 == 2^7 % 15 == 2^3 1000.... // +4k 229 2^M3 % M5 == 2^7 % 31 == 2^2 00100..... // +5k 230 2^M3 % M6 == 2^7 % 63 == 2^1 000010...... // +6k 231 2^M3 % M7 == 2^7 % 127 == 2^0 0000001....... 232 2^M3 % M8 == 2^7 % 255 == 2^7 10000000 233 2^M3 % M9 == 2^7 % 511 == 2^7 010000000 234 235 2^M4 % M2 == 2^15 % 3 == 2^1 10..--..--..--.. 236 2^M4 % M3 == 2^15 % 7 == 2^0 1...---...---... 237 2^M4 % M4 == 2^15 % 15 == 2^3 1000....----.... 238 2^M4 % M5 == 2^15 % 31 == 2^0 1.....-----..... 239 2^M4 % M6 == 2^15 % 63 == 2^3 1000......------ 240 2^M4 % M7 == 2^15 % 127 == 2^1 10.......------- 241 2^M4 % M8 == 2^15 % 255 == 2^7 10000000........ 242 2^M4 % M9 == 2^15 % 511 == 2^6 1000000......... 243 */ 244 switch { 245 case m < 2: 246 panic(0) 247 case e < 2: 248 return e 249 } 250 251 if x = mathutil.ModPowUint32(2, e, m); x == 0 { 252 return m - 1 253 } 254 255 return x - 1 256 } 257 258 // ModPow returns b^Me % Mm. Run time grows quickly with 'e' and/or 'm' when b 259 // != 2 (then ModPow2 is used). 260 func ModPow(b, e, m uint32) (r *big.Int) { 261 if m == 1 { 262 return big.NewInt(0) 263 } 264 265 if b == 2 { 266 x := ModPow2(e, m) 267 r = big.NewInt(0) 268 r.SetBit(r, int(x), 1) 269 return 270 } 271 272 bb := big.NewInt(int64(b)) 273 r = big.NewInt(1) 274 for ; e != 0; e-- { 275 r = bigfft.Mul(r, bb) 276 Mod(r, r, m) 277 bb = bigfft.Mul(bb, bb) 278 Mod(bb, bb, m) 279 } 280 return 281 } 282 283 // ProbablyPrime returns true if Mn is prime or is a pseudoprime to base a. 284 // Note: Every Mp, prime p, is a prime or is a pseudoprime to base 2, actually 285 // to every base 2^i, i ∊ [1, p). In contrast - it is conjectured (w/o any 286 // known counterexamples) that no composite Mp, prime p, is a pseudoprime to 287 // base 3. 288 func ProbablyPrime(n, a uint32) bool { 289 //TODO +test, +bench 290 if a == 2 { 291 return ModPow2(n-1, n) == 0 292 } 293 294 nMinus1 := New(n) 295 nMinus1.Sub(nMinus1, _1) 296 x := ModPow(a, n-1, n) 297 return x.Cmp(_1) == 0 || x.Cmp(nMinus1) == 0 298 }