mirror of https://github.com/k3s-io/k3s
150 lines
5.3 KiB
Go
150 lines
5.3 KiB
Go
|
// Copyright ©2013 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 mat
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"runtime"
|
||
|
|
||
|
"gonum.org/v1/gonum/lapack"
|
||
|
)
|
||
|
|
||
|
// Condition is the condition number of a matrix. The condition
|
||
|
// number is defined as |A| * |A^-1|.
|
||
|
//
|
||
|
// One important use of Condition is during linear solve routines (finding x such
|
||
|
// that A * x = b). The condition number of A indicates the accuracy of
|
||
|
// the computed solution. A Condition error will be returned if the condition
|
||
|
// number of A is sufficiently large. If A is exactly singular to working precision,
|
||
|
// Condition == ∞, and the solve algorithm may have completed early. If Condition
|
||
|
// is large and finite the solve algorithm will be performed, but the computed
|
||
|
// solution may be innacurate. Due to the nature of finite precision arithmetic,
|
||
|
// the value of Condition is only an approximate test of singularity.
|
||
|
type Condition float64
|
||
|
|
||
|
func (c Condition) Error() string {
|
||
|
return fmt.Sprintf("matrix singular or near-singular with condition number %.4e", c)
|
||
|
}
|
||
|
|
||
|
// ConditionTolerance is the tolerance limit of the condition number. If the
|
||
|
// condition number is above this value, the matrix is considered singular.
|
||
|
const ConditionTolerance = 1e16
|
||
|
|
||
|
const (
|
||
|
// CondNorm is the matrix norm used for computing the condition number by routines
|
||
|
// in the matrix packages.
|
||
|
CondNorm = lapack.MaxRowSum
|
||
|
|
||
|
// CondNormTrans is the norm used to compute on A^T to get the same result as
|
||
|
// computing CondNorm on A.
|
||
|
CondNormTrans = lapack.MaxColumnSum
|
||
|
)
|
||
|
|
||
|
const stackTraceBufferSize = 1 << 20
|
||
|
|
||
|
// Maybe will recover a panic with a type mat.Error from fn, and return this error
|
||
|
// as the Err field of an ErrorStack. The stack trace for the panicking function will be
|
||
|
// recovered and placed in the StackTrace field. Any other error is re-panicked.
|
||
|
func Maybe(fn func()) (err error) {
|
||
|
defer func() {
|
||
|
if r := recover(); r != nil {
|
||
|
if e, ok := r.(Error); ok {
|
||
|
if e.string == "" {
|
||
|
panic("mat: invalid error")
|
||
|
}
|
||
|
buf := make([]byte, stackTraceBufferSize)
|
||
|
n := runtime.Stack(buf, false)
|
||
|
err = ErrorStack{Err: e, StackTrace: string(buf[:n])}
|
||
|
return
|
||
|
}
|
||
|
panic(r)
|
||
|
}
|
||
|
}()
|
||
|
fn()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// MaybeFloat will recover a panic with a type mat.Error from fn, and return this error
|
||
|
// as the Err field of an ErrorStack. The stack trace for the panicking function will be
|
||
|
// recovered and placed in the StackTrace field. Any other error is re-panicked.
|
||
|
func MaybeFloat(fn func() float64) (f float64, err error) {
|
||
|
defer func() {
|
||
|
if r := recover(); r != nil {
|
||
|
if e, ok := r.(Error); ok {
|
||
|
if e.string == "" {
|
||
|
panic("mat: invalid error")
|
||
|
}
|
||
|
buf := make([]byte, stackTraceBufferSize)
|
||
|
n := runtime.Stack(buf, false)
|
||
|
err = ErrorStack{Err: e, StackTrace: string(buf[:n])}
|
||
|
return
|
||
|
}
|
||
|
panic(r)
|
||
|
}
|
||
|
}()
|
||
|
return fn(), nil
|
||
|
}
|
||
|
|
||
|
// MaybeComplex will recover a panic with a type mat.Error from fn, and return this error
|
||
|
// as the Err field of an ErrorStack. The stack trace for the panicking function will be
|
||
|
// recovered and placed in the StackTrace field. Any other error is re-panicked.
|
||
|
func MaybeComplex(fn func() complex128) (f complex128, err error) {
|
||
|
defer func() {
|
||
|
if r := recover(); r != nil {
|
||
|
if e, ok := r.(Error); ok {
|
||
|
if e.string == "" {
|
||
|
panic("mat: invalid error")
|
||
|
}
|
||
|
buf := make([]byte, stackTraceBufferSize)
|
||
|
n := runtime.Stack(buf, false)
|
||
|
err = ErrorStack{Err: e, StackTrace: string(buf[:n])}
|
||
|
return
|
||
|
}
|
||
|
panic(r)
|
||
|
}
|
||
|
}()
|
||
|
return fn(), nil
|
||
|
}
|
||
|
|
||
|
// Error represents matrix handling errors. These errors can be recovered by Maybe wrappers.
|
||
|
type Error struct{ string }
|
||
|
|
||
|
func (err Error) Error() string { return err.string }
|
||
|
|
||
|
var (
|
||
|
ErrIndexOutOfRange = Error{"matrix: index out of range"}
|
||
|
ErrRowAccess = Error{"matrix: row index out of range"}
|
||
|
ErrColAccess = Error{"matrix: column index out of range"}
|
||
|
ErrVectorAccess = Error{"matrix: vector index out of range"}
|
||
|
ErrZeroLength = Error{"matrix: zero length in matrix dimension"}
|
||
|
ErrRowLength = Error{"matrix: row length mismatch"}
|
||
|
ErrColLength = Error{"matrix: col length mismatch"}
|
||
|
ErrSquare = Error{"matrix: expect square matrix"}
|
||
|
ErrNormOrder = Error{"matrix: invalid norm order for matrix"}
|
||
|
ErrSingular = Error{"matrix: matrix is singular"}
|
||
|
ErrShape = Error{"matrix: dimension mismatch"}
|
||
|
ErrIllegalStride = Error{"matrix: illegal stride"}
|
||
|
ErrPivot = Error{"matrix: malformed pivot list"}
|
||
|
ErrTriangle = Error{"matrix: triangular storage mismatch"}
|
||
|
ErrTriangleSet = Error{"matrix: triangular set out of bounds"}
|
||
|
ErrBandSet = Error{"matrix: band set out of bounds"}
|
||
|
ErrDiagSet = Error{"matrix: diagonal set out of bounds"}
|
||
|
ErrSliceLengthMismatch = Error{"matrix: input slice length mismatch"}
|
||
|
ErrNotPSD = Error{"matrix: input not positive symmetric definite"}
|
||
|
ErrFailedEigen = Error{"matrix: eigendecomposition not successful"}
|
||
|
)
|
||
|
|
||
|
// ErrorStack represents matrix handling errors that have been recovered by Maybe wrappers.
|
||
|
type ErrorStack struct {
|
||
|
Err error
|
||
|
|
||
|
// StackTrace is the stack trace
|
||
|
// recovered by Maybe, MaybeFloat
|
||
|
// or MaybeComplex.
|
||
|
StackTrace string
|
||
|
}
|
||
|
|
||
|
func (err ErrorStack) Error() string { return err.Err.Error() }
|