mirror of
https://github.com/gonum/gonum.git
synced 2025-10-05 15:16:59 +08:00

Add copyright header to doc.go Keep original comment style (e.g. line comments and block comments). Fix doc comments containing multiple line comments. Remove vanity imports from all files except doc.go. Fixes #12. The source code of fixdocs is located at: https://play.golang.org/p/7RtYLzldsO
149 lines
4.2 KiB
Go
149 lines
4.2 KiB
Go
// Copyright ©2014 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 fd
|
|
|
|
import (
|
|
"math"
|
|
"runtime"
|
|
)
|
|
|
|
// A Point is a stencil location in a finite difference formula.
|
|
type Point struct {
|
|
Loc float64
|
|
Coeff float64
|
|
}
|
|
|
|
// Formula represents a finite difference formula on a regularly spaced grid
|
|
// that approximates the derivative of order k of a function f at x as
|
|
// d^k f(x) ≈ (1 / Step^k) * \sum_i Coeff_i * f(x + Step * Loc_i).
|
|
// Step must be positive, or the finite difference formula will panic.
|
|
type Formula struct {
|
|
// Stencil is the set of sampling Points which are used to estimate the
|
|
// derivative. The locations will be scaled by Step and are relative to x.
|
|
Stencil []Point
|
|
Derivative int // The order of the approximated derivative.
|
|
Step float64 // Default step size for the formula.
|
|
}
|
|
|
|
func (f Formula) isZero() bool {
|
|
return f.Stencil == nil && f.Derivative == 0 && f.Step == 0
|
|
}
|
|
|
|
// Settings is the settings structure for computing finite differences.
|
|
type Settings struct {
|
|
// Formula is the finite difference formula used
|
|
// for approximating the derivative.
|
|
// Zero value indicates a default formula.
|
|
Formula Formula
|
|
// Step is the distance between points of the stencil.
|
|
// If equal to 0, formula's default step will be used.
|
|
Step float64
|
|
|
|
OriginKnown bool // Flag that the value at the origin x is known.
|
|
OriginValue float64 // Value at the origin (only used if OriginKnown is true).
|
|
|
|
Concurrent bool // Should the function calls be executed concurrently.
|
|
}
|
|
|
|
// Forward represents a first-order accurate forward approximation
|
|
// to the first derivative.
|
|
var Forward = Formula{
|
|
Stencil: []Point{{Loc: 0, Coeff: -1}, {Loc: 1, Coeff: 1}},
|
|
Derivative: 1,
|
|
Step: 2e-8,
|
|
}
|
|
|
|
// Forward2nd represents a first-order accurate forward approximation
|
|
// to the second derivative.
|
|
var Forward2nd = Formula{
|
|
Stencil: []Point{{Loc: 0, Coeff: 1}, {Loc: 1, Coeff: -2}, {Loc: 2, Coeff: 1}},
|
|
Derivative: 2,
|
|
Step: 1e-4,
|
|
}
|
|
|
|
// Backward represents a first-order accurate backward approximation
|
|
// to the first derivative.
|
|
var Backward = Formula{
|
|
Stencil: []Point{{Loc: -1, Coeff: -1}, {Loc: 0, Coeff: 1}},
|
|
Derivative: 1,
|
|
Step: 2e-8,
|
|
}
|
|
|
|
// Backward2nd represents a first-order accurate forward approximation
|
|
// to the second derivative.
|
|
var Backward2nd = Formula{
|
|
Stencil: []Point{{Loc: 0, Coeff: 1}, {Loc: -1, Coeff: -2}, {Loc: -2, Coeff: 1}},
|
|
Derivative: 2,
|
|
Step: 1e-4,
|
|
}
|
|
|
|
// Central represents a second-order accurate centered approximation
|
|
// to the first derivative.
|
|
var Central = Formula{
|
|
Stencil: []Point{{Loc: -1, Coeff: -0.5}, {Loc: 1, Coeff: 0.5}},
|
|
Derivative: 1,
|
|
Step: 6e-6,
|
|
}
|
|
|
|
// Central2nd represents a secord-order accurate centered approximation
|
|
// to the second derivative.
|
|
var Central2nd = Formula{
|
|
Stencil: []Point{{Loc: -1, Coeff: 1}, {Loc: 0, Coeff: -2}, {Loc: 1, Coeff: 1}},
|
|
Derivative: 2,
|
|
Step: 1e-4,
|
|
}
|
|
|
|
var negativeStep = "fd: negative step"
|
|
|
|
// checkFormula checks if the formula is valid, and panics otherwise.
|
|
func checkFormula(formula Formula) {
|
|
if formula.Derivative == 0 || formula.Stencil == nil || formula.Step <= 0 {
|
|
panic("fd: bad formula")
|
|
}
|
|
}
|
|
|
|
// computeWorkers returns the desired number of workers given the concurrency
|
|
// level and number of evaluations.
|
|
func computeWorkers(concurrent bool, evals int) int {
|
|
if !concurrent {
|
|
return 1
|
|
}
|
|
nWorkers := runtime.GOMAXPROCS(0)
|
|
if nWorkers > evals {
|
|
nWorkers = evals
|
|
}
|
|
return nWorkers
|
|
}
|
|
|
|
// usesOrigin returns whether the stencil uses the origin, which is true iff
|
|
// one of the locations in the stencil equals 0.
|
|
func usesOrigin(stencil []Point) bool {
|
|
for _, pt := range stencil {
|
|
if pt.Loc == 0 {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// getOrigin returns the value at the origin. It returns originValue if originKnown
|
|
// is true. It returns the value returned by f if stencil contains a point with
|
|
// zero location, and NaN otherwise.
|
|
func getOrigin(originKnown bool, originValue float64, f func() float64, stencil []Point) float64 {
|
|
if originKnown {
|
|
return originValue
|
|
}
|
|
for _, pt := range stencil {
|
|
if pt.Loc == 0 {
|
|
return f()
|
|
}
|
|
}
|
|
return math.NaN()
|
|
}
|
|
|
|
const (
|
|
badDerivOrder = "fd: invalid derivative order"
|
|
)
|