gonum.org/v1/gonum@v0.14.0/integrate/quad/quad_test.go (about)

     1  // Copyright ©2015 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package quad
     6  
     7  import (
     8  	"math"
     9  	"testing"
    10  
    11  	"gonum.org/v1/gonum/floats/scalar"
    12  	"gonum.org/v1/gonum/stat/distuv"
    13  )
    14  
    15  func TestFixed(t *testing.T) {
    16  	t.Parallel()
    17  	for i, test := range []struct {
    18  		f        func(float64) float64
    19  		min, max float64
    20  		n        []int
    21  		tol      []float64
    22  		ans      float64
    23  	}{
    24  		// Tolerances determined from intuition and a bit of post-hoc tweaking.
    25  		{
    26  			f:   func(x float64) float64 { return math.Exp(x) },
    27  			min: -3,
    28  			max: 5,
    29  			n:   []int{3, 4, 6, 7, 15, 16, 300, 301},
    30  			tol: []float64{5e-2, 5e-3, 5e-6, 1e-7, 1e-14, 1e-14, 1e-14, 1e-14},
    31  			ans: math.Exp(5) - math.Exp(-3),
    32  		},
    33  		{
    34  			f:   distuv.UnitNormal.Prob,
    35  			min: math.Inf(-1),
    36  			max: math.Inf(1),
    37  			n:   []int{15, 16, 50, 51, 300, 301},
    38  			tol: []float64{5e-3, 1e-3, 1e-7, 1e-7, 1e-14, 1e-14},
    39  			ans: 1,
    40  		},
    41  		{
    42  			f:   func(x float64) float64 { return math.Exp(-x) },
    43  			min: 5,
    44  			max: math.Inf(1),
    45  			n:   []int{15, 16, 50, 51, 300, 301},
    46  			tol: []float64{5e-3, 1e-3, 1e-7, 1e-7, 1e-14, 1e-14},
    47  			ans: math.Exp(-5),
    48  		},
    49  		{
    50  			f:   func(x float64) float64 { return math.Exp(x) },
    51  			min: math.Inf(-1),
    52  			max: -5,
    53  			n:   []int{15, 16, 50, 51, 300, 301},
    54  			tol: []float64{5e-3, 1e-3, 1e-7, 1e-7, 1e-14, 1e-14},
    55  			ans: math.Exp(-5),
    56  		},
    57  		{
    58  			f:   func(x float64) float64 { return math.Exp(x) },
    59  			min: 3,
    60  			max: 3,
    61  			n:   []int{15, 16, 50, 51, 300, 301},
    62  			tol: []float64{0, 0, 0, 0, 0, 0},
    63  			ans: 0,
    64  		},
    65  	} {
    66  		for j, n := range test.n {
    67  			ans := Fixed(test.f, test.min, test.max, n, nil, 0)
    68  			if !scalar.EqualWithinAbsOrRel(ans, test.ans, test.tol[j], test.tol[j]) {
    69  				t.Errorf("Case %d, n = %d: Mismatch. Want %v, got %v", i, n, test.ans, ans)
    70  			}
    71  			ans2 := Fixed(test.f, test.min, test.max, n, nil, 3)
    72  			if !scalar.EqualWithinAbsOrRel(ans2, test.ans, test.tol[j], test.tol[j]) {
    73  				t.Errorf("Case %d, n = %d: Mismatch concurrent. Want %v, got %v", i, n, test.ans, ans)
    74  			}
    75  		}
    76  	}
    77  }
    78  
    79  // legendreNonSingle wraps Legendre but does not implement FixedLocationSingle.
    80  type legendreNonSingle struct {
    81  	Legendre Legendre
    82  }
    83  
    84  func (l legendreNonSingle) FixedLocations(x, weight []float64, min, max float64) {
    85  	l.Legendre.FixedLocations(x, weight, min, max)
    86  }
    87  
    88  func TestFixedNonSingle(t *testing.T) {
    89  	t.Parallel()
    90  	// TODO(btracey): Add tests with infinite bounds when we have native support
    91  	// for indefinite integrals.
    92  	for i, test := range []struct {
    93  		f        func(float64) float64
    94  		min, max float64
    95  		n        []int
    96  		tol      []float64
    97  		ans      float64
    98  	}{
    99  		// Tolerances determined from intuition and a bit of post-hoc tweaking.
   100  		{
   101  			f:   func(x float64) float64 { return math.Exp(x) },
   102  			min: -3,
   103  			max: 5,
   104  			n:   []int{3, 4, 6, 7, 15, 16, 300, 301},
   105  			tol: []float64{5e-2, 5e-3, 5e-6, 1e-7, 1e-14, 1e-14, 1e-14, 1e-14},
   106  			ans: math.Exp(5) - math.Exp(-3),
   107  		},
   108  		{
   109  			f:   func(x float64) float64 { return math.Exp(x) },
   110  			min: 3,
   111  			max: 3,
   112  			n:   []int{3, 4, 6, 7, 15, 16, 300, 301},
   113  			tol: []float64{0, 0, 0, 0, 0, 0, 0, 0},
   114  			ans: 0,
   115  		},
   116  	} {
   117  		for j, n := range test.n {
   118  			ans := Fixed(test.f, test.min, test.max, n, legendreNonSingle{}, 0)
   119  			if !scalar.EqualWithinAbsOrRel(ans, test.ans, test.tol[j], test.tol[j]) {
   120  				t.Errorf("Case = %d, n = %d: Mismatch. Want %v, got %v", i, n, test.ans, ans)
   121  			}
   122  			ans2 := Fixed(test.f, test.min, test.max, n, legendreNonSingle{}, 3)
   123  			if !scalar.EqualWithinAbsOrRel(ans2, test.ans, test.tol[j], test.tol[j]) {
   124  				t.Errorf("Case = %d, n = %d: Mismatch concurrent. Want %v, got %v", i, n, test.ans, ans)
   125  			}
   126  		}
   127  	}
   128  }