// Copyright (c) 2014 The mersenne Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. /* Package mersenne collects utilities related to Mersenne numbers[1] and/or some of their properties. Exponent In this documentation the term 'exponent' refers to 'n' of a Mersenne number Mn equal to 2^n-1. This package supports only uint32 sized exponents. New() currently supports exponents only up to math.MaxInt32 (31 bits, up to 256 MB required to represent such Mn in memory as a big.Int). Links Referenced from above: [1] http://en.wikipedia.org/wiki/Mersenne_number */ package mersenne import ( "math" "math/big" "github.com/cznic/mathutil" "github.com/remyoudompheng/bigfft" ) var ( _0 = big.NewInt(0) _1 = big.NewInt(1) _2 = big.NewInt(2) ) // Knowns list the exponent of currently (March 2012) known Mersenne primes // exponents in order. See also: http://oeis.org/A000043 for a partial list. var Knowns = []uint32{ 2, // #1 3, // #2 5, // #3 7, // #4 13, // #5 17, // #6 19, // #7 31, // #8 61, // #9 89, // #10 107, // #11 127, // #12 521, // #13 607, // #14 1279, // #15 2203, // #16 2281, // #17 3217, // #18 4253, // #19 4423, // #20 9689, // #21 9941, // #22 11213, // #23 19937, // #24 21701, // #25 23209, // #26 44497, // #27 86243, // #28 110503, // #29 132049, // #30 216091, // #31 756839, // #32 859433, // #33 1257787, // #34 1398269, // #35 2976221, // #36 3021377, // #37 6972593, // #38 13466917, // #39 20996011, // #40 24036583, // #41 25964951, // #42 30402457, // #43 32582657, // #44 37156667, // #45 42643801, // #46 43112609, // #47 57885161, // #48 74207281, // #49 } // Known maps the exponent of known Mersenne primes its ordinal number/rank. // Ranks > 41 are currently provisional. var Known map[uint32]int func init() { Known = map[uint32]int{} for i, v := range Knowns { Known[v] = i + 1 } } // New returns Mn == 2^n-1 for n <= math.MaxInt32 or nil otherwise. func New(n uint32) (m *big.Int) { if n > math.MaxInt32 { return } m = big.NewInt(0) return m.Sub(m.SetBit(m, int(n), 1), _1) } // HasFactorUint32 returns true if d | Mn. Typical run time for a 32 bit factor // and a 32 bit exponent is < 1 µs. func HasFactorUint32(d, n uint32) bool { return d == 1 || d&1 != 0 && mathutil.ModPowUint32(2, n, d) == 1 } // HasFactorUint64 returns true if d | Mn. Typical run time for a 64 bit factor // and a 32 bit exponent is < 30 µs. func HasFactorUint64(d uint64, n uint32) bool { return d == 1 || d&1 != 0 && mathutil.ModPowUint64(2, uint64(n), d) == 1 } // HasFactorBigInt returns true if d | Mn, d > 0. Typical run time for a 128 // bit factor and a 32 bit exponent is < 75 µs. func HasFactorBigInt(d *big.Int, n uint32) bool { return d.Cmp(_1) == 0 || d.Sign() > 0 && d.Bit(0) == 1 && mathutil.ModPowBigInt(_2, big.NewInt(int64(n)), d).Cmp(_1) == 0 } // HasFactorBigInt2 returns true if d | Mn, d > 0 func HasFactorBigInt2(d, n *big.Int) bool { return d.Cmp(_1) == 0 || d.Sign() > 0 && d.Bit(0) == 1 && mathutil.ModPowBigInt(_2, n, d).Cmp(_1) == 0 } /* FromFactorBigInt returns n such that d | Mn if n <= max and d is odd. In other cases zero is returned. It is conjectured that every odd d ∊ N divides infinitely many Mersenne numbers. The returned n should be the exponent of smallest such Mn. NOTE: The computation of n from a given d performs roughly in O(n). It is thus highly recomended to use the 'max' argument to limit the "searched" exponent upper bound as appropriate. Otherwise the computation can take a long time as a large factor can be a divisor of a Mn with exponent above the uint32 limits. The FromFactorBigInt function is a modification of the original Will Edgington's "reverse method", discussed here: http://tech.groups.yahoo.com/group/primenumbers/message/15061 */ func FromFactorBigInt(d *big.Int, max uint32) (n uint32) { if d.Bit(0) == 0 { return } var m big.Int for n < max { m.Add(&m, d) i := 0 for ; m.Bit(i) == 1; i++ { if n == math.MaxUint32 { return 0 } n++ } m.Rsh(&m, uint(i)) if m.Sign() == 0 { if n > max { n = 0 } return } } return 0 } // Mod sets mod to n % Mexp and returns mod. It panics for exp == 0 || exp >= // math.MaxInt32 || n < 0. func Mod(mod, n *big.Int, exp uint32) *big.Int { if exp == 0 || exp >= math.MaxInt32 || n.Sign() < 0 { panic(0) } m := New(exp) mod.Set(n) var x big.Int for mod.BitLen() > int(exp) { x.Set(mod) x.Rsh(&x, uint(exp)) mod.And(mod, m) mod.Add(mod, &x) } if mod.BitLen() == int(exp) && mod.Cmp(m) == 0 { mod.SetInt64(0) } return mod } // ModPow2 returns x such that 2^Me % Mm == 2^x. It panics for m < 2. Typical // run time is < 1 µs. Use instead of ModPow(2, e, m) wherever possible. func ModPow2(e, m uint32) (x uint32) { /* m < 2 -> panic e == 0 -> x == 0 e == 1 -> x == 1 2^M1 % M2 == 2^1 % 3 == 2^1 10 // 2^1, 3, 5, 7 ... +2k 2^M1 % M3 == 2^1 % 7 == 2^1 010 // 2^1, 4, 7, ... +3k 2^M1 % M4 == 2^1 % 15 == 2^1 0010 // 2^1, 5, 9, 13... +4k 2^M1 % M5 == 2^1 % 31 == 2^1 00010 // 2^1, 6, 11, 16... +5k 2^M2 % M2 == 2^3 % 3 == 2^1 10.. // 2^3, 5, 7, 9, 11, ... +2k 2^M2 % M3 == 2^3 % 7 == 2^0 001... // 2^3, 6, 9, 12, 15, ... +3k 2^M2 % M4 == 2^3 % 15 == 2^3 1000 // 2^3, 7, 11, 15, 19, ... +4k 2^M2 % M5 == 2^3 % 31 == 2^3 01000 // 2^3, 8, 13, 18, 23, ... +5k 2^M3 % M2 == 2^7 % 3 == 2^1 10..--.. // 2^3, 5, 7... +2k 2^M3 % M3 == 2^7 % 7 == 2^1 010...--- // 2^1, 4, 7... +3k 2^M3 % M4 == 2^7 % 15 == 2^3 1000.... // +4k 2^M3 % M5 == 2^7 % 31 == 2^2 00100..... // +5k 2^M3 % M6 == 2^7 % 63 == 2^1 000010...... // +6k 2^M3 % M7 == 2^7 % 127 == 2^0 0000001....... 2^M3 % M8 == 2^7 % 255 == 2^7 10000000 2^M3 % M9 == 2^7 % 511 == 2^7 010000000 2^M4 % M2 == 2^15 % 3 == 2^1 10..--..--..--.. 2^M4 % M3 == 2^15 % 7 == 2^0 1...---...---... 2^M4 % M4 == 2^15 % 15 == 2^3 1000....----.... 2^M4 % M5 == 2^15 % 31 == 2^0 1.....-----..... 2^M4 % M6 == 2^15 % 63 == 2^3 1000......------ 2^M4 % M7 == 2^15 % 127 == 2^1 10.......------- 2^M4 % M8 == 2^15 % 255 == 2^7 10000000........ 2^M4 % M9 == 2^15 % 511 == 2^6 1000000......... */ switch { case m < 2: panic(0) case e < 2: return e } if x = mathutil.ModPowUint32(2, e, m); x == 0 { return m - 1 } return x - 1 } // ModPow returns b^Me % Mm. Run time grows quickly with 'e' and/or 'm' when b // != 2 (then ModPow2 is used). func ModPow(b, e, m uint32) (r *big.Int) { if m == 1 { return big.NewInt(0) } if b == 2 { x := ModPow2(e, m) r = big.NewInt(0) r.SetBit(r, int(x), 1) return } bb := big.NewInt(int64(b)) r = big.NewInt(1) for ; e != 0; e-- { r = bigfft.Mul(r, bb) Mod(r, r, m) bb = bigfft.Mul(bb, bb) Mod(bb, bb, m) } return } // ProbablyPrime returns true if Mn is prime or is a pseudoprime to base a. // Note: Every Mp, prime p, is a prime or is a pseudoprime to base 2, actually // to every base 2^i, i ∊ [1, p). In contrast - it is conjectured (w/o any // known counterexamples) that no composite Mp, prime p, is a pseudoprime to // base 3. func ProbablyPrime(n, a uint32) bool { //TODO +test, +bench if a == 2 { return ModPow2(n-1, n) == 0 } nMinus1 := New(n) nMinus1.Sub(nMinus1, _1) x := ModPow(a, n-1, n) return x.Cmp(_1) == 0 || x.Cmp(nMinus1) == 0 }