github.com/gopherd/gonum@v0.0.4/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 "github.com/gopherd/gonum/floats/scalar" 12 "github.com/gopherd/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 }