This repository has been archived by the owner on Dec 10, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 51
/
errors.go
147 lines (129 loc) · 5.2 KB
/
errors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// 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 matrix
import (
"fmt"
"runtime"
"github.com/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 mat64.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("mat64: 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 mat64.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("mat64: 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 mat64.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("mat64: 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 definition"}
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"}
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() }