OSDN Git Service

new repo
[bytom/vapor.git] / vendor / gonum.org / v1 / gonum / mat / symband.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"
9         "gonum.org/v1/gonum/blas/blas64"
10 )
11
12 var (
13         symBandDense *SymBandDense
14         _            Matrix           = symBandDense
15         _            Symmetric        = symBandDense
16         _            Banded           = symBandDense
17         _            RawSymBander     = symBandDense
18         _            MutableSymBanded = symBandDense
19
20         _ NonZeroDoer    = symBandDense
21         _ RowNonZeroDoer = symBandDense
22         _ ColNonZeroDoer = symBandDense
23 )
24
25 // SymBandDense represents a symmetric band matrix in dense storage format.
26 type SymBandDense struct {
27         mat blas64.SymmetricBand
28 }
29
30 // MutableSymBanded is a symmetric band matrix interface type that allows elements
31 // to be altered.
32 type MutableSymBanded interface {
33         Symmetric
34         Bandwidth() (kl, ku int)
35         SetSymBand(i, j int, v float64)
36 }
37
38 // A RawSymBander can return a blas64.SymmetricBand representation of the receiver.
39 // Changes to the blas64.SymmetricBand.Data slice will be reflected in the original
40 // matrix, changes to the N, K, Stride and Uplo fields will not.
41 type RawSymBander interface {
42         RawSymBand() blas64.SymmetricBand
43 }
44
45 // NewSymBandDense creates a new SymBand matrix with n rows and columns. If data == nil,
46 // a new slice is allocated for the backing slice. If len(data) == n*(k+1),
47 // data is used as the backing slice, and changes to the elements of the returned
48 // SymBandDense will be reflected in data. If neither of these is true, NewSymBandDense
49 // will panic. k must be at least zero and less than n, otherwise NewBandDense will panic.
50 //
51 // The data must be arranged in row-major order constructed by removing the zeros
52 // from the rows outside the band and aligning the diagonals. SymBandDense matrices
53 // are stored in the upper triangle. For example, the matrix
54 //    1  2  3  0  0  0
55 //    2  4  5  6  0  0
56 //    3  5  7  8  9  0
57 //    0  6  8 10 11 12
58 //    0  0  9 11 13 14
59 //    0  0  0 12 14 15
60 // becomes (* entries are never accessed)
61 //     1  2  3
62 //     4  5  6
63 //     7  8  9
64 //    10 11 12
65 //    13 14  *
66 //    15  *  *
67 // which is passed to NewBandDense as []float64{1, 2, 3, 4, ...} with k=2.
68 // Only the values in the band portion of the matrix are used.
69 func NewSymBandDense(n, k int, data []float64) *SymBandDense {
70         if n < 0 || k < 0 {
71                 panic("mat: negative dimension")
72         }
73         if k+1 > n {
74                 panic("mat: band out of range")
75         }
76         bc := k + 1
77         if data != nil && len(data) != n*bc {
78                 panic(ErrShape)
79         }
80         if data == nil {
81                 data = make([]float64, n*bc)
82         }
83         return &SymBandDense{
84                 mat: blas64.SymmetricBand{
85                         N:      n,
86                         K:      k,
87                         Stride: bc,
88                         Uplo:   blas.Upper,
89                         Data:   data,
90                 },
91         }
92 }
93
94 // NewDiagonal is a convenience function that returns a diagonal matrix represented by a
95 // SymBandDense. The length of data must be n or data must be nil, otherwise NewDiagonal
96 // will panic.
97 func NewDiagonal(n int, data []float64) *SymBandDense {
98         return NewSymBandDense(n, 0, data)
99 }
100
101 // Dims returns the number of rows and columns in the matrix.
102 func (s *SymBandDense) Dims() (r, c int) {
103         return s.mat.N, s.mat.N
104 }
105
106 // Symmetric returns the size of the receiver.
107 func (s *SymBandDense) Symmetric() int {
108         return s.mat.N
109 }
110
111 // Bandwidth returns the bandwidths of the matrix.
112 func (s *SymBandDense) Bandwidth() (kl, ku int) {
113         return s.mat.K, s.mat.K
114 }
115
116 // T implements the Matrix interface. Symmetric matrices, by definition, are
117 // equal to their transpose, and this is a no-op.
118 func (s *SymBandDense) T() Matrix {
119         return s
120 }
121
122 // TBand implements the Banded interface.
123 func (s *SymBandDense) TBand() Banded {
124         return s
125 }
126
127 // RawSymBand returns the underlying blas64.SymBand used by the receiver.
128 // Changes to elements in the receiver following the call will be reflected
129 // in returned blas64.SymBand.
130 func (s *SymBandDense) RawSymBand() blas64.SymmetricBand {
131         return s.mat
132 }
133
134 // DoNonZero calls the function fn for each of the non-zero elements of s. The function fn
135 // takes a row/column index and the element value of s at (i, j).
136 func (s *SymBandDense) DoNonZero(fn func(i, j int, v float64)) {
137         for i := 0; i < s.mat.N; i++ {
138                 for j := max(0, i-s.mat.K); j < min(s.mat.N, i+s.mat.K+1); j++ {
139                         v := s.at(i, j)
140                         if v != 0 {
141                                 fn(i, j, v)
142                         }
143                 }
144         }
145 }
146
147 // DoRowNonZero calls the function fn for each of the non-zero elements of row i of s. The function fn
148 // takes a row/column index and the element value of s at (i, j).
149 func (s *SymBandDense) DoRowNonZero(i int, fn func(i, j int, v float64)) {
150         if i < 0 || s.mat.N <= i {
151                 panic(ErrRowAccess)
152         }
153         for j := max(0, i-s.mat.K); j < min(s.mat.N, i+s.mat.K+1); j++ {
154                 v := s.at(i, j)
155                 if v != 0 {
156                         fn(i, j, v)
157                 }
158         }
159 }
160
161 // DoColNonZero calls the function fn for each of the non-zero elements of column j of s. The function fn
162 // takes a row/column index and the element value of s at (i, j).
163 func (s *SymBandDense) DoColNonZero(j int, fn func(i, j int, v float64)) {
164         if j < 0 || s.mat.N <= j {
165                 panic(ErrColAccess)
166         }
167         for i := 0; i < s.mat.N; i++ {
168                 if i-s.mat.K <= j && j < i+s.mat.K+1 {
169                         v := s.at(i, j)
170                         if v != 0 {
171                                 fn(i, j, v)
172                         }
173                 }
174         }
175 }