|  | // 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 ( | 
|  | "fmt" | 
|  | "strings" | 
|  | "testing" | 
|  | "unicode" | 
|  | ) | 
|  |  | 
|  | var primes = []string{ | 
|  | "2", | 
|  | "3", | 
|  | "5", | 
|  | "7", | 
|  | "11", | 
|  |  | 
|  | "13756265695458089029", | 
|  | "13496181268022124907", | 
|  | "10953742525620032441", | 
|  | "17908251027575790097", | 
|  |  | 
|  | // https://golang.org/issue/638 | 
|  | "18699199384836356663", | 
|  |  | 
|  | "98920366548084643601728869055592650835572950932266967461790948584315647051443", | 
|  | "94560208308847015747498523884063394671606671904944666360068158221458669711639", | 
|  |  | 
|  | // https://primes.utm.edu/lists/small/small3.html | 
|  | "449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163", | 
|  | "230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593", | 
|  | "5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993", | 
|  | "203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123", | 
|  |  | 
|  | // ECC primes: https://tools.ietf.org/html/draft-ladd-safecurves-02 | 
|  | "3618502788666131106986593281521497120414687020801267626233049500247285301239",                                                                                  // Curve1174: 2^251-9 | 
|  | "57896044618658097711785492504343953926634992332820282019728792003956564819949",                                                                                 // Curve25519: 2^255-19 | 
|  | "9850501549098619803069760025035903451269934817616361666987073351061430442874302652853566563721228910201656997576599",                                           // E-382: 2^382-105 | 
|  | "42307582002575910332922579714097346549017899709713998034217522897561970639123926132812109468141778230245837569601494931472367",                                 // Curve41417: 2^414-17 | 
|  | "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", // E-521: 2^521-1 | 
|  | } | 
|  |  | 
|  | var composites = []string{ | 
|  | "0", | 
|  | "1", | 
|  | "21284175091214687912771199898307297748211672914763848041968395774954376176754", | 
|  | "6084766654921918907427900243509372380954290099172559290432744450051395395951", | 
|  | "84594350493221918389213352992032324280367711247940675652888030554255915464401", | 
|  | "82793403787388584738507275144194252681", | 
|  |  | 
|  | // Arnault, "Rabin-Miller Primality Test: Composite Numbers Which Pass It", | 
|  | // Mathematics of Computation, 64(209) (January 1995), pp. 335-361. | 
|  | "1195068768795265792518361315725116351898245581", // strong pseudoprime to prime bases 2 through 29 | 
|  | // strong pseudoprime to all prime bases up to 200 | 
|  | ` | 
|  | 80383745745363949125707961434194210813883768828755814583748891752229 | 
|  | 74273765333652186502336163960045457915042023603208766569966760987284 | 
|  | 0439654082329287387918508691668573282677617710293896977394701670823 | 
|  | 0428687109997439976544144845341155872450633409279022275296229414984 | 
|  | 2306881685404326457534018329786111298960644845216191652872597534901`, | 
|  |  | 
|  | // Extra-strong Lucas pseudoprimes. https://oeis.org/A217719 | 
|  | "989", | 
|  | "3239", | 
|  | "5777", | 
|  | "10877", | 
|  | "27971", | 
|  | "29681", | 
|  | "30739", | 
|  | "31631", | 
|  | "39059", | 
|  | "72389", | 
|  | "73919", | 
|  | "75077", | 
|  | "100127", | 
|  | "113573", | 
|  | "125249", | 
|  | "137549", | 
|  | "137801", | 
|  | "153931", | 
|  | "155819", | 
|  | "161027", | 
|  | "162133", | 
|  | "189419", | 
|  | "218321", | 
|  | "231703", | 
|  | "249331", | 
|  | "370229", | 
|  | "429479", | 
|  | "430127", | 
|  | "459191", | 
|  | "473891", | 
|  | "480689", | 
|  | "600059", | 
|  | "621781", | 
|  | "632249", | 
|  | "635627", | 
|  |  | 
|  | "3673744903", | 
|  | "3281593591", | 
|  | "2385076987", | 
|  | "2738053141", | 
|  | "2009621503", | 
|  | "1502682721", | 
|  | "255866131", | 
|  | "117987841", | 
|  | "587861", | 
|  |  | 
|  | "6368689", | 
|  | "8725753", | 
|  | "80579735209", | 
|  | "105919633", | 
|  | } | 
|  |  | 
|  | func cutSpace(r rune) rune { | 
|  | if unicode.IsSpace(r) { | 
|  | return -1 | 
|  | } | 
|  | return r | 
|  | } | 
|  |  | 
|  | func TestProbablyPrime(t *testing.T) { | 
|  | nreps := 20 | 
|  | if testing.Short() { | 
|  | nreps = 3 | 
|  | } | 
|  | for i, s := range primes { | 
|  | p, _ := new(Int).SetString(s, 10) | 
|  | if !p.ProbablyPrime(nreps) || !p.ProbablyPrime(1) || !p.ProbablyPrime(0) { | 
|  | t.Errorf("#%d prime found to be non-prime (%s)", i, s) | 
|  | } | 
|  | } | 
|  |  | 
|  | for i, s := range composites { | 
|  | s = strings.Map(cutSpace, s) | 
|  | c, _ := new(Int).SetString(s, 10) | 
|  | if c.ProbablyPrime(nreps) || c.ProbablyPrime(1) || c.ProbablyPrime(0) { | 
|  | t.Errorf("#%d composite found to be prime (%s)", i, s) | 
|  | } | 
|  | } | 
|  |  | 
|  | // check that ProbablyPrime panics if n <= 0 | 
|  | c := NewInt(11) // a prime | 
|  | for _, n := range []int{-1, 0, 1} { | 
|  | func() { | 
|  | defer func() { | 
|  | if n < 0 && recover() == nil { | 
|  | t.Fatalf("expected panic from ProbablyPrime(%d)", n) | 
|  | } | 
|  | }() | 
|  | if !c.ProbablyPrime(n) { | 
|  | t.Fatalf("%v should be a prime", c) | 
|  | } | 
|  | }() | 
|  | } | 
|  | } | 
|  |  | 
|  | func BenchmarkProbablyPrime(b *testing.B) { | 
|  | p, _ := new(Int).SetString("203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123", 10) | 
|  | for _, n := range []int{0, 1, 5, 10, 20} { | 
|  | b.Run(fmt.Sprintf("n=%d", n), func(b *testing.B) { | 
|  | for i := 0; i < b.N; i++ { | 
|  | p.ProbablyPrime(n) | 
|  | } | 
|  | }) | 
|  | } | 
|  |  | 
|  | b.Run("Lucas", func(b *testing.B) { | 
|  | for i := 0; i < b.N; i++ { | 
|  | p.abs.probablyPrimeLucas() | 
|  | } | 
|  | }) | 
|  | b.Run("MillerRabinBase2", func(b *testing.B) { | 
|  | for i := 0; i < b.N; i++ { | 
|  | p.abs.probablyPrimeMillerRabin(1, true) | 
|  | } | 
|  | }) | 
|  | } | 
|  |  | 
|  | func TestMillerRabinPseudoprimes(t *testing.T) { | 
|  | testPseudoprimes(t, "probablyPrimeMillerRabin", | 
|  | func(n nat) bool { return n.probablyPrimeMillerRabin(1, true) && !n.probablyPrimeLucas() }, | 
|  | // https://oeis.org/A001262 | 
|  | []int{2047, 3277, 4033, 4681, 8321, 15841, 29341, 42799, 49141, 52633, 65281, 74665, 80581, 85489, 88357, 90751}) | 
|  | } | 
|  |  | 
|  | func TestLucasPseudoprimes(t *testing.T) { | 
|  | testPseudoprimes(t, "probablyPrimeLucas", | 
|  | func(n nat) bool { return n.probablyPrimeLucas() && !n.probablyPrimeMillerRabin(1, true) }, | 
|  | // https://oeis.org/A217719 | 
|  | []int{989, 3239, 5777, 10877, 27971, 29681, 30739, 31631, 39059, 72389, 73919, 75077}) | 
|  | } | 
|  |  | 
|  | func testPseudoprimes(t *testing.T, name string, cond func(nat) bool, want []int) { | 
|  | n := nat{1} | 
|  | for i := 3; i < 100000; i += 2 { | 
|  | n[0] = Word(i) | 
|  | pseudo := cond(n) | 
|  | if pseudo && (len(want) == 0 || i != want[0]) { | 
|  | t.Errorf("%s(%v, base=2) = true, want false", name, i) | 
|  | } else if !pseudo && len(want) >= 1 && i == want[0] { | 
|  | t.Errorf("%s(%v, base=2) = false, want true", name, i) | 
|  | } | 
|  | if len(want) > 0 && i == want[0] { | 
|  | want = want[1:] | 
|  | } | 
|  | } | 
|  | if len(want) > 0 { | 
|  | t.Fatalf("forgot to test %v", want) | 
|  | } | 
|  | } |