// Test the two generic access functions in prime.go, Primes() and // Iterator(). Also test that the generators agree on all primes under // a somewhat bigger limit. // // Use basic sieve as a reference, compare it to other generators. func TestGeneric(t *testing.T) { const limit = 1000 // exercise generic function Primes on sieve. reference := prime.Primes(sieve.New(limit), 0, limit) gloop: for _, gen := range []prime.Generator{ segment.New(limit), queue.PQueue{}, sprp.New(), } { // exercise generic function Iterator on other generators. ch := prime.Iterator(gen, 0, limit) for i, pRef := range reference { switch p, ok := <-ch; { case !ok: t.Errorf("%s.Iterator(0, %d) didn't find all primes.", reflect.TypeOf(gen), limit) continue gloop case p != pRef: t.Errorf("%dth prime? sieve says %d, %s says %d\n", i+1, pRef, reflect.TypeOf(gen), p) continue gloop } } if _, ok := <-ch; ok { t.Errorf("%s.Iterator(0, %d) returning too many primes.\n", reflect.TypeOf(gen), limit) } } }
// Some more tests. // Nothing here should invoke the Eratosthenes algorithm. func TestSmall(t *testing.T) { // reproduce 10 primes hardcoded right here. ten := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} n := ten[9] s := New(n) if s.Limit() < n { t.Fatal("Limit of", n, "expected. Got", s.Limit()) } // check that the 10 are right var i int s.Iterate(0, n, func(prime uint64) (termiate bool) { if prime != ten[i] { t.Fatal("Incorrect prime. Expected", ten[i], "got", prime) } i++ return }) // resieve, getting all precomputed primes n = 3 * bitsPerInt * uint64(len(smallComposites)) s.Init(n) // s.isComposites shouldn't have grown if len(s.isComposite) != len(smallComposites) { t.Error("Sieve didn't recognize small n") } // use handy PrimeGenerator function to save primes for next test smallPrimes := prime.Primes(s) // test InitPi on boundary case of small np s.InitPi(uint64(len(smallPrimes))) if s.Lim != n { t.Error("SievePi didn't seem to work on small np") } // asking for one more prime than was precomputed should trigger sieve. s.InitPi(1 + uint64(len(smallPrimes))) if len(s.isComposite) <= len(smallComposites) { t.Fatal("sieve didn't seem to work", len(s.isComposite), len(smallComposites)) } // check that primes from sieve match precomputed primes from // previous test. test IterateFunc early termination feature // in the process. var j uint64 ok := s.Iterate(0, s.Lim, func(prime uint64) bool { if int(j) == len(smallPrimes) { return true } if prime != smallPrimes[j] { t.Fatalf("sieve failed. expected %d for prime[%d]. got %d.\n", smallPrimes[j], j, prime) } j++ return false }) if !ok { t.Error("Iterate returned false on early termination.") } }