fix(integrate): name IntegrateFunction in quadrature errors

This commit is contained in:
2026-09-28 10:21:52 +02:00
parent a4000c0a82
commit e8a6e1cdd3
3 changed files with 10 additions and 8 deletions
+2
View File
@@ -43,6 +43,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `TriangleMesh2D.BoundaryEdges` returns the mesh's own edges: the - `TriangleMesh2D.BoundaryEdges` returns the mesh's own edges: the
boundary pairs sort as pairs, never as one flat index list that boundary pairs sort as pairs, never as one flat index list that
interleaves the endpoints of unrelated edges. interleaves the endpoints of unrelated edges.
- `IntegrateFunction` names itself in its errors; the adaptive
quadrature no longer reports under a name absent from the surface.
## [1.0.0] - 2026-09-03 ## [1.0.0] - 2026-09-03
+1 -1
View File
@@ -286,7 +286,7 @@ func IntegrateND(f func(x []float64) float64, lower, upper []float64, opts Cubat
total := rootVal total := rootVal
totalEst := rootEst totalEst := rootEst
// The stopping rule scales the tolerance with the magnitude of the // The stopping rule scales the tolerance with the magnitude of the
// integral, the way Integrate combines its bounds: the error // integral, the way IntegrateFunction combines its bounds: the error
// estimate of an integral of size 1e6 cannot fall below the // estimate of an integral of size 1e6 cannot fall below the
// rounding floor of the sum itself, so a purely absolute tolerance // rounding floor of the sum itself, so a purely absolute tolerance
// would burn the whole budget and report an exhausted budget // would burn the whole budget and report an exhausted budget
+7 -7
View File
@@ -25,8 +25,8 @@ import (
// rational substitution before the rule runs; an integrand over an // rational substitution before the rule runs; an integrand over an
// infinite interval has to decay to zero for this to converge. // infinite interval has to decay to zero for this to converge.
// QuadratureOptions tunes Integrate. RelTol ≤ 0 means 1e-10, AbsTol // QuadratureOptions tunes IntegrateFunction. RelTol ≤ 0 means 1e-10,
// ≤ 0 means 1e-12, MaxIntervals ≤ 0 means 256. // AbsTol ≤ 0 means 1e-12, MaxIntervals ≤ 0 means 256.
type QuadratureOptions struct { type QuadratureOptions struct {
RelTol float64 RelTol float64
AbsTol float64 AbsTol float64
@@ -131,7 +131,7 @@ func IntegrateFunction(f func(x float64) (float64, error), a, b float64, opts Qu
opts.MaxIntervals = 256 opts.MaxIntervals = 256
} }
if math.IsNaN(a) || math.IsNaN(b) { if math.IsNaN(a) || math.IsNaN(b) {
return 0, 0, base.Errf("Integrate: bounds must not be NaN") return 0, 0, base.Errf("IntegrateFunction: bounds must not be NaN")
} }
sign := 1.0 sign := 1.0
if b < a { if b < a {
@@ -229,7 +229,7 @@ func IntegrateFunction(f func(x float64) (float64, error), a, b float64, opts Qu
first, err := measure(lo, hi) first, err := measure(lo, hi)
if err != nil { if err != nil {
return 0, 0, base.Errf("Integrate: %w", err) return 0, 0, base.Errf("IntegrateFunction: %w", err)
} }
leaves := []leaf{first} leaves := []leaf{first}
budget := func() (total, errSum float64) { budget := func() (total, errSum float64) {
@@ -242,7 +242,7 @@ func IntegrateFunction(f func(x float64) (float64, error), a, b float64, opts Qu
value, errSum := budget() value, errSum := budget()
for errSum > math.Max(opts.AbsTol, opts.RelTol*math.Abs(value)) { for errSum > math.Max(opts.AbsTol, opts.RelTol*math.Abs(value)) {
if len(leaves) >= opts.MaxIntervals { if len(leaves) >= opts.MaxIntervals {
return 0, 0, base.Errf("Integrate: error estimate %g exceeds the tolerance within %d subintervals", return 0, 0, base.Errf("IntegrateFunction: error estimate %g exceeds the tolerance within %d subintervals",
errSum, opts.MaxIntervals) errSum, opts.MaxIntervals)
} }
// Bisect the leaf that contributes the most error. // Bisect the leaf that contributes the most error.
@@ -255,11 +255,11 @@ func IntegrateFunction(f func(x float64) (float64, error), a, b float64, opts Qu
w := leaves[worst] w := leaves[worst]
left, lerr := measure(w.l, (w.l+w.r)/2) left, lerr := measure(w.l, (w.l+w.r)/2)
if lerr != nil { if lerr != nil {
return 0, 0, base.Errf("Integrate: %w", lerr) return 0, 0, base.Errf("IntegrateFunction: %w", lerr)
} }
right, rerr := measure((w.l+w.r)/2, w.r) right, rerr := measure((w.l+w.r)/2, w.r)
if rerr != nil { if rerr != nil {
return 0, 0, base.Errf("Integrate: %w", rerr) return 0, 0, base.Errf("IntegrateFunction: %w", rerr)
} }
leaves[worst] = left leaves[worst] = left
leaves = append(leaves, right) leaves = append(leaves, right)