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.
8 "gonum.org/v1/gonum/blas/blas64"
15 _ RawBander = bandDense
17 _ NonZeroDoer = bandDense
18 _ RowNonZeroDoer = bandDense
19 _ ColNonZeroDoer = bandDense
22 // BandDense represents a band matrix in dense storage format.
23 type BandDense struct {
27 // Banded is a band matrix representation.
28 type Banded interface {
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)
34 // TBand is the equivalent of the T() method in the Matrix
35 // interface but guarantees the transpose is of banded type.
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 {
46 // A MutableBanded can set elements of a band matrix.
47 type MutableBanded interface {
49 SetBand(i, j int, v float64)
53 _ Matrix = TransposeBand{}
54 _ Banded = TransposeBand{}
55 _ UntransposeBander = TransposeBand{}
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 {
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)
71 // Dims returns the dimensions of the transposed matrix.
72 func (t TransposeBand) Dims() (r, c int) {
73 c, r = t.Banded.Dims()
77 // T performs an implicit transpose by returning the Banded field.
78 func (t TransposeBand) T() Matrix {
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()
89 // TBand performs an implicit transpose by returning the Banded field.
90 func (t TransposeBand) TBand() Banded {
94 // Untranspose returns the Banded field.
95 func (t TransposeBand) Untranspose() Matrix {
99 // UntransposeBand returns the Banded field.
100 func (t TransposeBand) UntransposeBand() Banded {
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.
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
119 // becomes (* entries are never accessed)
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")
132 if kl+1 > r || ku+1 > c {
133 panic("mat: band out of range")
136 if data != nil && len(data) != min(r, c+kl)*bc {
140 data = make([]float64, min(r, c+kl)*bc)
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)
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
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
170 // T performs an implicit transpose by returning the receiver inside a Transpose.
171 func (b *BandDense) T() Matrix {
175 // TBand performs an implicit transpose by returning the receiver inside a TransposeBand.
176 func (b *BandDense) TBand() Banded {
177 return TransposeBand{b}
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 {
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++ {
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 {
206 for j := max(0, i-b.mat.KL); j < min(b.mat.Cols, i+b.mat.KU+1); j++ {
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 {
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 {