Exemple #1
0
// 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.")
	}
}