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  }