// Copyright 2016 The Go 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 big

import 

// ProbablyPrime reports whether x is probably prime,
// applying the Miller-Rabin test with n pseudorandomly chosen bases
// as well as a Baillie-PSW test.
//
// If x is prime, ProbablyPrime returns true.
// If x is chosen randomly and not prime, ProbablyPrime probably returns false.
// The probability of returning true for a randomly chosen non-prime is at most ¼ⁿ.
//
// ProbablyPrime is 100% accurate for inputs less than 2⁶⁴.
// See Menezes et al., Handbook of Applied Cryptography, 1997, pp. 145-149,
// and FIPS 186-4 Appendix F for further discussion of the error probabilities.
//
// ProbablyPrime is not suitable for judging primes that an adversary may
// have crafted to fool the test.
//
// As of Go 1.8, ProbablyPrime(0) is allowed and applies only a Baillie-PSW test.
// Before Go 1.8, ProbablyPrime applied only the Miller-Rabin tests, and ProbablyPrime(0) panicked.
func ( *Int) ( int) bool {
	// Note regarding the doc comment above:
	// It would be more precise to say that the Baillie-PSW test uses the
	// extra strong Lucas test as its Lucas test, but since no one knows
	// how to tell any of the Lucas tests apart inside a Baillie-PSW test
	// (they all work equally well empirically), that detail need not be
	// documented or implicitly guaranteed.
	// The comment does avoid saying "the" Baillie-PSW test
	// because of this general ambiguity.

	if  < 0 {
		panic("negative n for ProbablyPrime")
	}
	if .neg || len(.abs) == 0 {
		return false
	}

	// primeBitMask records the primes < 64.
	const  uint64 = 1<<2 | 1<<3 | 1<<5 | 1<<7 |
		1<<11 | 1<<13 | 1<<17 | 1<<19 | 1<<23 | 1<<29 | 1<<31 |
		1<<37 | 1<<41 | 1<<43 | 1<<47 | 1<<53 | 1<<59 | 1<<61

	 := .abs[0]
	if len(.abs) == 1 &&  < 64 {
		return &(1<<) != 0
	}

	if &1 == 0 {
		return false // x is even
	}

	const  = 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 37
	const  = 29 * 31 * 41 * 43 * 47 * 53

	var ,  uint32
	switch _W {
	case 32:
		 = uint32(.abs.modW())
		 = uint32(.abs.modW())
	case 64:
		 := .abs.modW(( * ) & _M)
		 = uint32( % )
		 = uint32( % )
	default:
		panic("math/big: invalid word size")
	}

	if %3 == 0 || %5 == 0 || %7 == 0 || %11 == 0 || %13 == 0 || %17 == 0 || %19 == 0 || %23 == 0 || %37 == 0 ||
		%29 == 0 || %31 == 0 || %41 == 0 || %43 == 0 || %47 == 0 || %53 == 0 {
		return false
	}

	return .abs.probablyPrimeMillerRabin(+1, true) && .abs.probablyPrimeLucas()
}

// probablyPrimeMillerRabin reports whether n passes reps rounds of the
// Miller-Rabin primality test, using pseudo-randomly chosen bases.
// If force2 is true, one of the rounds is forced to use base 2.
// See Handbook of Applied Cryptography, p. 139, Algorithm 4.24.
// The number n is known to be non-zero.
func ( nat) ( int,  bool) bool {
	 := nat(nil).sub(, natOne)
	// determine q, k such that nm1 = q << k
	 := .trailingZeroBits()
	 := nat(nil).shr(, )

	 := nat(nil).sub(, natTwo)
	 := rand.New(rand.NewSource(int64([0])))

	var , ,  nat
	 := .bitLen()

:
	for  := 0;  < ; ++ {
		if  == -1 &&  {
			 = .set(natTwo)
		} else {
			 = .random(, , )
			 = .add(, natTwo)
		}
		 = .expNN(, , , false)
		if .cmp(natOne) == 0 || .cmp() == 0 {
			continue
		}
		for  := uint(1);  < ; ++ {
			 = .sqr()
			,  = .div(, , )
			if .cmp() == 0 {
				continue 
			}
			if .cmp(natOne) == 0 {
				return false
			}
		}
		return false
	}

	return true
}

// probablyPrimeLucas reports whether n passes the "almost extra strong" Lucas probable prime test,
// using Baillie-OEIS parameter selection. This corresponds to "AESLPSP" on Jacobsen's tables (link below).
// The combination of this test and a Miller-Rabin/Fermat test with base 2 gives a Baillie-PSW test.
//
// References:
//
// Baillie and Wagstaff, "Lucas Pseudoprimes", Mathematics of Computation 35(152),
// October 1980, pp. 1391-1417, especially page 1401.
// https://www.ams.org/journals/mcom/1980-35-152/S0025-5718-1980-0583518-6/S0025-5718-1980-0583518-6.pdf
//
// Grantham, "Frobenius Pseudoprimes", Mathematics of Computation 70(234),
// March 2000, pp. 873-891.
// https://www.ams.org/journals/mcom/2001-70-234/S0025-5718-00-01197-2/S0025-5718-00-01197-2.pdf
//
// Baillie, "Extra strong Lucas pseudoprimes", OEIS A217719, https://oeis.org/A217719.
//
// Jacobsen, "Pseudoprime Statistics, Tables, and Data", http://ntheory.org/pseudoprimes.html.
//
// Nicely, "The Baillie-PSW Primality Test", https://web.archive.org/web/20191121062007/http://www.trnicely.net/misc/bpsw.html.
// (Note that Nicely's definition of the "extra strong" test gives the wrong Jacobi condition,
// as pointed out by Jacobsen.)
//
// Crandall and Pomerance, Prime Numbers: A Computational Perspective, 2nd ed.
// Springer, 2005.
func ( nat) () bool {
	// Discard 0, 1.
	if len() == 0 || .cmp(natOne) == 0 {
		return false
	}
	// Two is the only even prime.
	// Already checked by caller, but here to allow testing in isolation.
	if [0]&1 == 0 {
		return .cmp(natTwo) == 0
	}

	// Baillie-OEIS "method C" for choosing D, P, Q,
	// as in https://oeis.org/A217719/a217719.txt:
	// try increasing P ≥ 3 such that D = P² - 4 (so Q = 1)
	// until Jacobi(D, n) = -1.
	// The search is expected to succeed for non-square n after just a few trials.
	// After more than expected failures, check whether n is square
	// (which would cause Jacobi(D, n) = 1 for all D not dividing n).
	 := Word(3)
	 := nat{1}
	 := nat(nil) // temp
	 := &Int{abs: }
	 := &Int{abs: }
	for ; ; ++ {
		if  > 10000 {
			// This is widely believed to be impossible.
			// If we get a report, we'll want the exact number n.
			panic("math/big: internal error: cannot find (D/n) = -1 for " + .String())
		}
		[0] = * - 4
		 := Jacobi(, )
		if  == -1 {
			break
		}
		if  == 0 {
			// d = p²-4 = (p-2)(p+2).
			// If (d/n) == 0 then d shares a prime factor with n.
			// Since the loop proceeds in increasing p and starts with p-2==1,
			// the shared prime factor must be p+2.
			// If p+2 == n, then n is prime; otherwise p+2 is a proper factor of n.
			return len() == 1 && [0] == +2
		}
		if  == 40 {
			// We'll never find (d/n) = -1 if n is a square.
			// If n is a non-square we expect to find a d in just a few attempts on average.
			// After 40 attempts, take a moment to check if n is indeed a square.
			 = .sqrt()
			 = .sqr()
			if .cmp() == 0 {
				return false
			}
		}
	}

	// Grantham definition of "extra strong Lucas pseudoprime", after Thm 2.3 on p. 876
	// (D, P, Q above have become Δ, b, 1):
	//
	// Let U_n = U_n(b, 1), V_n = V_n(b, 1), and Δ = b²-4.
	// An extra strong Lucas pseudoprime to base b is a composite n = 2^r s + Jacobi(Δ, n),
	// where s is odd and gcd(n, 2*Δ) = 1, such that either (i) U_s ≡ 0 mod n and V_s ≡ ±2 mod n,
	// or (ii) V_{2^t s} ≡ 0 mod n for some 0 ≤ t < r-1.
	//
	// We know gcd(n, Δ) = 1 or else we'd have found Jacobi(d, n) == 0 above.
	// We know gcd(n, 2) = 1 because n is odd.
	//
	// Arrange s = (n - Jacobi(Δ, n)) / 2^r = (n+1) / 2^r.
	 := nat(nil).add(, natOne)
	 := int(.trailingZeroBits())
	 = .shr(, uint())
	 := nat(nil).sub(, natTwo) // n-2

	// We apply the "almost extra strong" test, which checks the above conditions
	// except for U_s ≡ 0 mod n, which allows us to avoid computing any U_k values.
	// Jacobsen points out that maybe we should just do the full extra strong test:
	// "It is also possible to recover U_n using Crandall and Pomerance equation 3.13:
	// U_n = D^-1 (2V_{n+1} - PV_n) allowing us to run the full extra-strong test
	// at the cost of a single modular inversion. This computation is easy and fast in GMP,
	// so we can get the full extra-strong test at essentially the same performance as the
	// almost extra strong test."

	// Compute Lucas sequence V_s(b, 1), where:
	//
	//	V(0) = 2
	//	V(1) = P
	//	V(k) = P V(k-1) - Q V(k-2).
	//
	// (Remember that due to method C above, P = b, Q = 1.)
	//
	// In general V(k) = α^k + β^k, where α and β are roots of x² - Px + Q.
	// Crandall and Pomerance (p.147) observe that for 0 ≤ j ≤ k,
	//
	//	V(j+k) = V(j)V(k) - V(k-j).
	//
	// So in particular, to quickly double the subscript:
	//
	//	V(2k) = V(k)² - 2
	//	V(2k+1) = V(k) V(k+1) - P
	//
	// We can therefore start with k=0 and build up to k=s in log₂(s) steps.
	 := nat(nil).setWord()
	 := nat(nil).setWord(2)
	 := nat(nil).setWord()
	 := nat(nil) // temp
	for  := int(.bitLen());  >= 0; -- {
		if .bit(uint()) != 0 {
			// k' = 2k+1
			// V(k') = V(2k+1) = V(k) V(k+1) - P.
			 = .mul(, )
			 = .add(, )
			 = .sub(, )
			,  = .div(, , )
			// V(k'+1) = V(2k+2) = V(k+1)² - 2.
			 = .sqr()
			 = .add(, )
			,  = .div(, , )
		} else {
			// k' = 2k
			// V(k'+1) = V(2k+1) = V(k) V(k+1) - P.
			 = .mul(, )
			 = .add(, )
			 = .sub(, )
			,  = .div(, , )
			// V(k') = V(2k) = V(k)² - 2
			 = .sqr()
			 = .add(, )
			,  = .div(, , )
		}
	}

	// Now k=s, so vk = V(s). Check V(s) ≡ ±2 (mod n).
	if .cmp(natTwo) == 0 || .cmp() == 0 {
		// Check U(s) ≡ 0.
		// As suggested by Jacobsen, apply Crandall and Pomerance equation 3.13:
		//
		//	U(k) = D⁻¹ (2 V(k+1) - P V(k))
		//
		// Since we are checking for U(k) == 0 it suffices to check 2 V(k+1) == P V(k) mod n,
		// or P V(k) - 2 V(k+1) == 0 mod n.
		 := .mul(, )
		 := .shl(, 1)
		if .cmp() < 0 {
			,  = , 
		}
		 = .sub(, )
		 :=  // steal vk1, no longer needed below
		 = nil
		_ = 
		,  = .div(, , )
		if len() == 0 {
			return true
		}
	}

	// Check V(2^t s) ≡ 0 mod n for some 0 ≤ t < r-1.
	for  := 0;  < -1; ++ {
		if len() == 0 { // vk == 0
			return true
		}
		// Optimization: V(k) = 2 is a fixed point for V(k') = V(k)² - 2,
		// so if V(k) = 2, we can stop: we will never find a future V(k) == 0.
		if len() == 1 && [0] == 2 { // vk == 2
			return false
		}
		// k' = 2k
		// V(k') = V(2k) = V(k)² - 2
		 = .sqr()
		 = .sub(, natTwo)
		,  = .div(, , )
	}
	return false
}