gonum.org/v1/gonum@v0.14.0/mat/errors.go (about) 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. 4 5 package mat 6 7 import ( 8 "fmt" 9 "runtime" 10 11 "gonum.org/v1/gonum/lapack" 12 ) 13 14 // Condition is the condition number of a matrix. The condition 15 // number is defined as |A| * |A^-1|. 16 // 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 inaccurate. Due to the nature of finite precision arithmetic, 24 // the value of Condition is only an approximate test of singularity. 25 type Condition float64 26 27 func (c Condition) Error() string { 28 return fmt.Sprintf("matrix singular or near-singular with condition number %.4e", c) 29 } 30 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 34 35 const ( 36 // CondNorm is the matrix norm used for computing the condition number by routines 37 // in the matrix packages. 38 CondNorm = lapack.MaxRowSum 39 40 // CondNormTrans is the norm used to compute on Aᵀ to get the same result as 41 // computing CondNorm on A. 42 CondNormTrans = lapack.MaxColumnSum 43 ) 44 45 const stackTraceBufferSize = 1 << 20 46 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) { 51 defer func() { 52 if r := recover(); r != nil { 53 if e, ok := r.(Error); ok { 54 if e.string == "" { 55 panic("mat: invalid error") 56 } 57 buf := make([]byte, stackTraceBufferSize) 58 n := runtime.Stack(buf, false) 59 err = ErrorStack{Err: e, StackTrace: string(buf[:n])} 60 return 61 } 62 panic(r) 63 } 64 }() 65 fn() 66 return 67 } 68 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) { 73 defer func() { 74 if r := recover(); r != nil { 75 if e, ok := r.(Error); ok { 76 if e.string == "" { 77 panic("mat: invalid error") 78 } 79 buf := make([]byte, stackTraceBufferSize) 80 n := runtime.Stack(buf, false) 81 err = ErrorStack{Err: e, StackTrace: string(buf[:n])} 82 return 83 } 84 panic(r) 85 } 86 }() 87 return fn(), nil 88 } 89 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) { 94 defer func() { 95 if r := recover(); r != nil { 96 if e, ok := r.(Error); ok { 97 if e.string == "" { 98 panic("mat: invalid error") 99 } 100 buf := make([]byte, stackTraceBufferSize) 101 n := runtime.Stack(buf, false) 102 err = ErrorStack{Err: e, StackTrace: string(buf[:n])} 103 return 104 } 105 panic(r) 106 } 107 }() 108 return fn(), nil 109 } 110 111 // Error represents matrix handling errors. These errors can be recovered by Maybe wrappers. 112 type Error struct{ string } 113 114 func (err Error) Error() string { return err.string } 115 116 var ( 117 ErrNegativeDimension = Error{"mat: negative dimension"} 118 ErrIndexOutOfRange = Error{"mat: index out of range"} 119 ErrReuseNonEmpty = Error{"mat: reuse of non-empty matrix"} 120 ErrRowAccess = Error{"mat: row index out of range"} 121 ErrColAccess = Error{"mat: column index out of range"} 122 ErrVectorAccess = Error{"mat: vector index out of range"} 123 ErrZeroLength = Error{"mat: zero length in matrix dimension"} 124 ErrRowLength = Error{"mat: row length mismatch"} 125 ErrColLength = Error{"mat: col length mismatch"} 126 ErrSquare = Error{"mat: expect square matrix"} 127 ErrNormOrder = Error{"mat: invalid norm order for matrix"} 128 ErrSingular = Error{"mat: matrix is singular"} 129 ErrShape = Error{"mat: dimension mismatch"} 130 ErrIllegalStride = Error{"mat: illegal stride"} 131 ErrPivot = Error{"mat: malformed pivot list"} 132 ErrTriangle = Error{"mat: triangular storage mismatch"} 133 ErrTriangleSet = Error{"mat: triangular set out of bounds"} 134 ErrBandwidth = Error{"mat: bandwidth out of range"} 135 ErrBandSet = Error{"mat: band set out of bounds"} 136 ErrDiagSet = Error{"mat: diagonal set out of bounds"} 137 ErrSliceLengthMismatch = Error{"mat: input slice length mismatch"} 138 ErrNotPSD = Error{"mat: input not positive symmetric definite"} 139 ErrFailedEigen = Error{"mat: eigendecomposition not successful"} 140 ) 141 142 // ErrorStack represents matrix handling errors that have been recovered by Maybe wrappers. 143 type ErrorStack struct { 144 Err error 145 146 // StackTrace is the stack trace 147 // recovered by Maybe, MaybeFloat 148 // or MaybeComplex. 149 StackTrace string 150 } 151 152 func (err ErrorStack) Error() string { return err.Err.Error() } 153 154 const badCap = "mat: bad capacity"