diff --git a/errors.go b/errors.go index c09971b..fda377a 100644 --- a/errors.go +++ b/errors.go @@ -4,21 +4,13 @@ package optimize -import "errors" +import ( + "errors" + "fmt" + "math" +) var ( - // ErrInf signifies the initial function value is infinite. - ErrInf = errors.New("optimize: initial function value is infinite") - - // ErrNaN signifies the initial function value is NaN. - ErrNaN = errors.New("optimize: initial function value is NaN") - - // ErrGradInf signifies that a component of the initial gradient is infinite. - ErrGradInf = errors.New("optimize: initial gradient is infinite") - - // ErrGradNaN signifies that a component of the initial gradient is NaN. - ErrGradNaN = errors.New("optimize: initial gradient is NaN") - // ErrZeroDimensional signifies an optimization was called with an input of length 0. ErrZeroDimensional = errors.New("optimize: zero dimensional input") @@ -36,3 +28,36 @@ var ( // due to floating-point arithmetic. ErrNoProgress = errors.New("linesearch: no change in location after Linesearcher step") ) + +// ErrFunc is returned when an initial function value is invalid. The error +// state may be either +Inf or NaN. ErrFunc satisfies the error interface. +type ErrFunc float64 + +func (err ErrFunc) Error() string { + switch { + case math.IsInf(float64(err), 1): + return "optimize: initial function value is infinite" + case math.IsNaN(float64(err)): + return "optimize: initial function value is NaN" + default: + panic("optimize: bad ErrFunc") + } +} + +// ErrGrad is returned when an initial gradient is invalid. The error gradient +// may be either ±Inf or NaN. ErrGrad satisfies the error interface. +type ErrGrad struct { + Grad float64 // Grad is the invalid gradient value. + Index int // Index is the position at which the invalid gradient was found. +} + +func (err ErrGrad) Error() string { + switch { + case math.IsInf(err.Grad, 0): + return fmt.Sprintf("optimize: initial gradient is infinite at position %d", err.Index) + case math.IsNaN(err.Grad): + return fmt.Sprintf("optimize: initial gradient is NaN at position %d", err.Index) + default: + panic("optimize: bad ErrGrad") + } +} diff --git a/local.go b/local.go index 962f2ee..540c2be 100644 --- a/local.go +++ b/local.go @@ -290,18 +290,12 @@ func getStartingLocation(p *Problem, method Method, initX []float64, stats *Stat evaluate(p, loc, eval, stats) } - if math.IsNaN(loc.F) { - return loc, ErrNaN + if math.IsInf(loc.F, 1) || math.IsNaN(loc.F) { + return loc, ErrFunc(loc.F) } - if math.IsInf(loc.F, 1) { - return loc, ErrInf - } - for _, v := range loc.Gradient { - if math.IsInf(v, 0) { - return loc, ErrGradInf - } - if math.IsNaN(v) { - return loc, ErrGradNaN + for i, v := range loc.Gradient { + if math.IsInf(v, 0) || math.IsNaN(v) { + return loc, ErrGrad{Grad: v, Index: i} } }