OSDN Git Service

new repo
[bytom/vapor.git] / vendor / gonum.org / v1 / gonum / mat / errors.go
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 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
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^T 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         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"}
136 )
137
138 // ErrorStack represents matrix handling errors that have been recovered by Maybe wrappers.
139 type ErrorStack struct {
140         Err error
141
142         // StackTrace is the stack trace
143         // recovered by Maybe, MaybeFloat
144         // or MaybeComplex.
145         StackTrace string
146 }
147
148 func (err ErrorStack) Error() string { return err.Err.Error() }