// Copyright ©2016 The Gonum 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 integrate import ( "math" "testing" "golang.org/x/exp/rand" "gonum.org/v1/gonum/integrate/testquad" ) func TestTrapezoidal(t *testing.T) { t.Parallel() rnd := rand.New(rand.NewSource(1)) for i, test := range []struct { integral testquad.Integral n int tol float64 }{ {integral: testquad.Constant(0), n: 2, tol: 0}, {integral: testquad.Constant(0), n: 10, tol: 0}, {integral: testquad.Poly(0), n: 2, tol: 1e-14}, {integral: testquad.Poly(0), n: 10, tol: 1e-14}, {integral: testquad.Poly(1), n: 2, tol: 1e-14}, {integral: testquad.Poly(1), n: 10, tol: 1e-14}, {integral: testquad.Poly(2), n: 1e5, tol: 1e-8}, {integral: testquad.Poly(3), n: 1e5, tol: 1e-8}, {integral: testquad.Poly(4), n: 1e5, tol: 1e-7}, {integral: testquad.Poly(5), n: 1e5, tol: 1e-7}, {integral: testquad.Sin(), n: 1e5, tol: 1e-11}, {integral: testquad.XExpMinusX(), n: 1e5, tol: 1e-10}, {integral: testquad.Sqrt(), n: 1e5, tol: 1e-8}, {integral: testquad.ExpOverX2Plus1(), n: 1e5, tol: 1e-10}, } { n := test.n a := test.integral.A b := test.integral.B x := jitterSpan(n, a, b, rnd) y := make([]float64, n) for i, xi := range x { y[i] = test.integral.F(xi) } got := Trapezoidal(x, y) want := test.integral.Value diff := math.Abs(got - want) if diff > test.tol { t.Errorf("Test #%d: %v, n=%v: unexpected result; got=%v want=%v diff=%v", i, test.integral.Name, n, got, want, diff) } } } func jitterSpan(n int, a, b float64, rnd *rand.Rand) []float64 { dx := (b - a) / float64(n-1) x := make([]float64, n) x[0] = a for i := 1; i < n-1; i++ { // Set x[i] to its regular location. x[i] = a + float64(i)*dx // Generate a random number in [-1,1). jitter := 2*rnd.Float64() - 1 // Jitter x[i] without crossing over its neighbors. x[i] += 0.4 * jitter * dx } x[n-1] = b return x }