OSDN Git Service

test (#52)
[bytom/vapor.git] / vendor / gonum.org / v1 / gonum / mat / band.go
1 // Copyright ©2017 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         "gonum.org/v1/gonum/blas/blas64"
9 )
10
11 var (
12         bandDense *BandDense
13         _         Matrix    = bandDense
14         _         Banded    = bandDense
15         _         RawBander = bandDense
16
17         _ NonZeroDoer    = bandDense
18         _ RowNonZeroDoer = bandDense
19         _ ColNonZeroDoer = bandDense
20 )
21
22 // BandDense represents a band matrix in dense storage format.
23 type BandDense struct {
24         mat blas64.Band
25 }
26
27 // Banded is a band matrix representation.
28 type Banded interface {
29         Matrix
30         // Bandwidth returns the lower and upper bandwidth values for
31         // the matrix. The total bandwidth of the matrix is kl+ku+1.
32         Bandwidth() (kl, ku int)
33
34         // TBand is the equivalent of the T() method in the Matrix
35         // interface but guarantees the transpose is of banded type.
36         TBand() Banded
37 }
38
39 // A RawBander can return a blas64.Band representation of the receiver.
40 // Changes to the blas64.Band.Data slice will be reflected in the original
41 // matrix, changes to the Rows, Cols, KL, KU and Stride fields will not.
42 type RawBander interface {
43         RawBand() blas64.Band
44 }
45
46 // A MutableBanded can set elements of a band matrix.
47 type MutableBanded interface {
48         Banded
49         SetBand(i, j int, v float64)
50 }
51
52 var (
53         _ Matrix            = TransposeBand{}
54         _ Banded            = TransposeBand{}
55         _ UntransposeBander = TransposeBand{}
56 )
57
58 // TransposeBand is a type for performing an implicit transpose of a band
59 // matrix. It implements the Banded interface, returning values from the
60 // transpose of the matrix within.
61 type TransposeBand struct {
62         Banded Banded
63 }
64
65 // At returns the value of the element at row i and column j of the transposed
66 // matrix, that is, row j and column i of the Banded field.
67 func (t TransposeBand) At(i, j int) float64 {
68         return t.Banded.At(j, i)
69 }
70
71 // Dims returns the dimensions of the transposed matrix.
72 func (t TransposeBand) Dims() (r, c int) {
73         c, r = t.Banded.Dims()
74         return r, c
75 }
76
77 // T performs an implicit transpose by returning the Banded field.
78 func (t TransposeBand) T() Matrix {
79         return t.Banded
80 }
81
82 // Bandwidth returns the lower and upper bandwidth values for
83 // the transposed matrix.
84 func (t TransposeBand) Bandwidth() (kl, ku int) {
85         kl, ku = t.Banded.Bandwidth()
86         return ku, kl
87 }
88
89 // TBand performs an implicit transpose by returning the Banded field.
90 func (t TransposeBand) TBand() Banded {
91         return t.Banded
92 }
93
94 // Untranspose returns the Banded field.
95 func (t TransposeBand) Untranspose() Matrix {
96         return t.Banded
97 }
98
99 // UntransposeBand returns the Banded field.
100 func (t TransposeBand) UntransposeBand() Banded {
101         return t.Banded
102 }
103
104 // NewBandDense creates a new Band matrix with r rows and c columns. If data == nil,
105 // a new slice is allocated for the backing slice. If len(data) == min(r, c+kl)*(kl+ku+1),
106 // data is used as the backing slice, and changes to the elements of the returned
107 // BandDense will be reflected in data. If neither of these is true, NewBandDense
108 // will panic. kl must be at least zero and less r, and ku must be at least zero and
109 // less than c, otherwise NewBandDense will panic.
110 //
111 // The data must be arranged in row-major order constructed by removing the zeros
112 // from the rows outside the band and aligning the diagonals. For example, the matrix
113 //    1  2  3  0  0  0
114 //    4  5  6  7  0  0
115 //    0  8  9 10 11  0
116 //    0  0 12 13 14 15
117 //    0  0  0 16 17 18
118 //    0  0  0  0 19 20
119 // becomes (* entries are never accessed)
120 //     *  1  2  3
121 //     4  5  6  7
122 //     8  9 10 11
123 //    12 13 14 15
124 //    16 17 18  *
125 //    19 20  *  *
126 // which is passed to NewBandDense as []float64{*, 1, 2, 3, 4, ...} with kl=1 and ku=2.
127 // Only the values in the band portion of the matrix are used.
128 func NewBandDense(r, c, kl, ku int, data []float64) *BandDense {
129         if r < 0 || c < 0 || kl < 0 || ku < 0 {
130                 panic("mat: negative dimension")
131         }
132         if kl+1 > r || ku+1 > c {
133                 panic("mat: band out of range")
134         }
135         bc := kl + ku + 1
136         if data != nil && len(data) != min(r, c+kl)*bc {
137                 panic(ErrShape)
138         }
139         if data == nil {
140                 data = make([]float64, min(r, c+kl)*bc)
141         }
142         return &BandDense{
143                 mat: blas64.Band{
144                         Rows:   r,
145                         Cols:   c,
146                         KL:     kl,
147                         KU:     ku,
148                         Stride: bc,
149                         Data:   data,
150                 },
151         }
152 }
153
154 // NewDiagonalRect is a convenience function that returns a diagonal matrix represented by a
155 // BandDense. The length of data must be min(r, c) otherwise NewDiagonalRect will panic.
156 func NewDiagonalRect(r, c int, data []float64) *BandDense {
157         return NewBandDense(r, c, 0, 0, data)
158 }
159
160 // Dims returns the number of rows and columns in the matrix.
161 func (b *BandDense) Dims() (r, c int) {
162         return b.mat.Rows, b.mat.Cols
163 }
164
165 // Bandwidth returns the upper and lower bandwidths of the matrix.
166 func (b *BandDense) Bandwidth() (kl, ku int) {
167         return b.mat.KL, b.mat.KU
168 }
169
170 // T performs an implicit transpose by returning the receiver inside a Transpose.
171 func (b *BandDense) T() Matrix {
172         return Transpose{b}
173 }
174
175 // TBand performs an implicit transpose by returning the receiver inside a TransposeBand.
176 func (b *BandDense) TBand() Banded {
177         return TransposeBand{b}
178 }
179
180 // RawBand returns the underlying blas64.Band used by the receiver.
181 // Changes to elements in the receiver following the call will be reflected
182 // in returned blas64.Band.
183 func (b *BandDense) RawBand() blas64.Band {
184         return b.mat
185 }
186
187 // DoNonZero calls the function fn for each of the non-zero elements of b. The function fn
188 // takes a row/column index and the element value of b at (i, j).
189 func (b *BandDense) DoNonZero(fn func(i, j int, v float64)) {
190         for i := 0; i < min(b.mat.Rows, b.mat.Cols+b.mat.KL); i++ {
191                 for j := max(0, i-b.mat.KL); j < min(b.mat.Cols, i+b.mat.KU+1); j++ {
192                         v := b.at(i, j)
193                         if v != 0 {
194                                 fn(i, j, v)
195                         }
196                 }
197         }
198 }
199
200 // DoRowNonZero calls the function fn for each of the non-zero elements of row i of b. The function fn
201 // takes a row/column index and the element value of b at (i, j).
202 func (b *BandDense) DoRowNonZero(i int, fn func(i, j int, v float64)) {
203         if i < 0 || b.mat.Rows <= i {
204                 panic(ErrRowAccess)
205         }
206         for j := max(0, i-b.mat.KL); j < min(b.mat.Cols, i+b.mat.KU+1); j++ {
207                 v := b.at(i, j)
208                 if v != 0 {
209                         fn(i, j, v)
210                 }
211         }
212 }
213
214 // DoColNonZero calls the function fn for each of the non-zero elements of column j of b. The function fn
215 // takes a row/column index and the element value of b at (i, j).
216 func (b *BandDense) DoColNonZero(j int, fn func(i, j int, v float64)) {
217         if j < 0 || b.mat.Cols <= j {
218                 panic(ErrColAccess)
219         }
220         for i := 0; i < min(b.mat.Rows, b.mat.Cols+b.mat.KL); i++ {
221                 if i-b.mat.KL <= j && j < i+b.mat.KU+1 {
222                         v := b.at(i, j)
223                         if v != 0 {
224                                 fn(i, j, v)
225                         }
226                 }
227         }
228 }