1 // Copyright ©2013 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.
11 "gonum.org/v1/gonum/lapack"
14 // Condition is the condition number of a matrix. The condition
15 // number is defined as |A| * |A^-1|.
17 // One important use of Condition is during linear solve routines (finding x such
18 // that A * x = b). The condition number of A indicates the accuracy of
19 // the computed solution. A Condition error will be returned if the condition
20 // number of A is sufficiently large. If A is exactly singular to working precision,
21 // Condition == ∞, and the solve algorithm may have completed early. If Condition
22 // is large and finite the solve algorithm will be performed, but the computed
23 // solution may be innacurate. Due to the nature of finite precision arithmetic,
24 // the value of Condition is only an approximate test of singularity.
25 type Condition float64
27 func (c Condition) Error() string {
28 return fmt.Sprintf("matrix singular or near-singular with condition number %.4e", c)
31 // ConditionTolerance is the tolerance limit of the condition number. If the
32 // condition number is above this value, the matrix is considered singular.
33 const ConditionTolerance = 1e16
36 // CondNorm is the matrix norm used for computing the condition number by routines
37 // in the matrix packages.
38 CondNorm = lapack.MaxRowSum
40 // CondNormTrans is the norm used to compute on A^T to get the same result as
41 // computing CondNorm on A.
42 CondNormTrans = lapack.MaxColumnSum
45 const stackTraceBufferSize = 1 << 20
47 // Maybe will recover a panic with a type mat.Error from fn, and return this error
48 // as the Err field of an ErrorStack. The stack trace for the panicking function will be
49 // recovered and placed in the StackTrace field. Any other error is re-panicked.
50 func Maybe(fn func()) (err error) {
52 if r := recover(); r != nil {
53 if e, ok := r.(Error); ok {
55 panic("mat: invalid error")
57 buf := make([]byte, stackTraceBufferSize)
58 n := runtime.Stack(buf, false)
59 err = ErrorStack{Err: e, StackTrace: string(buf[:n])}
69 // MaybeFloat will recover a panic with a type mat.Error from fn, and return this error
70 // as the Err field of an ErrorStack. The stack trace for the panicking function will be
71 // recovered and placed in the StackTrace field. Any other error is re-panicked.
72 func MaybeFloat(fn func() float64) (f float64, err error) {
74 if r := recover(); r != nil {
75 if e, ok := r.(Error); ok {
77 panic("mat: invalid error")
79 buf := make([]byte, stackTraceBufferSize)
80 n := runtime.Stack(buf, false)
81 err = ErrorStack{Err: e, StackTrace: string(buf[:n])}
90 // MaybeComplex will recover a panic with a type mat.Error from fn, and return this error
91 // as the Err field of an ErrorStack. The stack trace for the panicking function will be
92 // recovered and placed in the StackTrace field. Any other error is re-panicked.
93 func MaybeComplex(fn func() complex128) (f complex128, err error) {
95 if r := recover(); r != nil {
96 if e, ok := r.(Error); ok {
98 panic("mat: invalid error")
100 buf := make([]byte, stackTraceBufferSize)
101 n := runtime.Stack(buf, false)
102 err = ErrorStack{Err: e, StackTrace: string(buf[:n])}
111 // Error represents matrix handling errors. These errors can be recovered by Maybe wrappers.
112 type Error struct{ string }
114 func (err Error) Error() string { return err.string }
117 ErrIndexOutOfRange = Error{"matrix: index out of range"}
118 ErrRowAccess = Error{"matrix: row index out of range"}
119 ErrColAccess = Error{"matrix: column index out of range"}
120 ErrVectorAccess = Error{"matrix: vector index out of range"}
121 ErrZeroLength = Error{"matrix: zero length in matrix definition"}
122 ErrRowLength = Error{"matrix: row length mismatch"}
123 ErrColLength = Error{"matrix: col length mismatch"}
124 ErrSquare = Error{"matrix: expect square matrix"}
125 ErrNormOrder = Error{"matrix: invalid norm order for matrix"}
126 ErrSingular = Error{"matrix: matrix is singular"}
127 ErrShape = Error{"matrix: dimension mismatch"}
128 ErrIllegalStride = Error{"matrix: illegal stride"}
129 ErrPivot = Error{"matrix: malformed pivot list"}
130 ErrTriangle = Error{"matrix: triangular storage mismatch"}
131 ErrTriangleSet = Error{"matrix: triangular set out of bounds"}
132 ErrBandSet = Error{"matrix: band set out of bounds"}
133 ErrSliceLengthMismatch = Error{"matrix: input slice length mismatch"}
134 ErrNotPSD = Error{"matrix: input not positive symmetric definite"}
135 ErrFailedEigen = Error{"matrix: eigendecomposition not successful"}
138 // ErrorStack represents matrix handling errors that have been recovered by Maybe wrappers.
139 type ErrorStack struct {
142 // StackTrace is the stack trace
143 // recovered by Maybe, MaybeFloat
148 func (err ErrorStack) Error() string { return err.Err.Error() }