1// Copyright ©2019 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 5package mat 6 7import "gonum.org/v1/gonum/blas/cblas128" 8 9// Dense is a dense matrix representation with complex data. 10type CDense struct { 11 mat cblas128.General 12 13 capRows, capCols int 14} 15 16// Dims returns the number of rows and columns in the matrix. 17func (m *CDense) Dims() (r, c int) { 18 return m.mat.Rows, m.mat.Cols 19} 20 21// H performs an implicit conjugate transpose by returning the receiver inside a 22// Conjugate. 23func (m *CDense) H() CMatrix { 24 return Conjugate{m} 25} 26 27// NewCDense creates a new complex Dense matrix with r rows and c columns. 28// If data == nil, a new slice is allocated for the backing slice. 29// If len(data) == r*c, data is used as the backing slice, and changes to the 30// elements of the returned CDense will be reflected in data. 31// If neither of these is true, NewCDense will panic. 32// NewCDense will panic if either r or c is zero. 33// 34// The data must be arranged in row-major order, i.e. the (i*c + j)-th 35// element in the data slice is the {i, j}-th element in the matrix. 36func NewCDense(r, c int, data []complex128) *CDense { 37 if r <= 0 || c <= 0 { 38 if r == 0 || c == 0 { 39 panic(ErrZeroLength) 40 } 41 panic("mat: negative dimension") 42 } 43 if data != nil && r*c != len(data) { 44 panic(ErrShape) 45 } 46 if data == nil { 47 data = make([]complex128, r*c) 48 } 49 return &CDense{ 50 mat: cblas128.General{ 51 Rows: r, 52 Cols: c, 53 Stride: c, 54 Data: data, 55 }, 56 capRows: r, 57 capCols: c, 58 } 59} 60 61// reuseAs resizes an empty matrix to a r×c matrix, 62// or checks that a non-empty matrix is r×c. 63// 64// reuseAs must be kept in sync with reuseAsZeroed. 65func (m *CDense) reuseAs(r, c int) { 66 if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { 67 // Panic as a string, not a mat.Error. 68 panic("mat: caps not correctly set") 69 } 70 if r == 0 || c == 0 { 71 panic(ErrZeroLength) 72 } 73 if m.IsZero() { 74 m.mat = cblas128.General{ 75 Rows: r, 76 Cols: c, 77 Stride: c, 78 Data: useC(m.mat.Data, r*c), 79 } 80 m.capRows = r 81 m.capCols = c 82 return 83 } 84 if r != m.mat.Rows || c != m.mat.Cols { 85 panic(ErrShape) 86 } 87} 88 89func (m *CDense) reuseAsZeroed(r, c int) { 90 // This must be kept in-sync with reuseAs. 91 if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { 92 // Panic as a string, not a mat.Error. 93 panic("mat: caps not correctly set") 94 } 95 if r == 0 || c == 0 { 96 panic(ErrZeroLength) 97 } 98 if m.IsZero() { 99 m.mat = cblas128.General{ 100 Rows: r, 101 Cols: c, 102 Stride: c, 103 Data: useZeroedC(m.mat.Data, r*c), 104 } 105 m.capRows = r 106 m.capCols = c 107 return 108 } 109 if r != m.mat.Rows || c != m.mat.Cols { 110 panic(ErrShape) 111 } 112 m.Zero() 113} 114 115// Reset zeros the dimensions of the matrix so that it can be reused as the 116// receiver of a dimensionally restricted operation. 117// 118// See the Reseter interface for more information. 119func (m *CDense) Reset() { 120 // Row, Cols and Stride must be zeroed in unison. 121 m.mat.Rows, m.mat.Cols, m.mat.Stride = 0, 0, 0 122 m.capRows, m.capCols = 0, 0 123 m.mat.Data = m.mat.Data[:0] 124} 125 126// IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the 127// receiver for size-restricted operations. CDense matrices can be zeroed using Reset. 128func (m *CDense) IsZero() bool { 129 // It must be the case that m.Dims() returns 130 // zeros in this case. See comment in Reset(). 131 return m.mat.Stride == 0 132} 133 134// Zero sets all of the matrix elements to zero. 135func (m *CDense) Zero() { 136 r := m.mat.Rows 137 c := m.mat.Cols 138 for i := 0; i < r; i++ { 139 zeroC(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) 140 } 141} 142 143// Copy makes a copy of elements of a into the receiver. It is similar to the 144// built-in copy; it copies as much as the overlap between the two matrices and 145// returns the number of rows and columns it copied. If a aliases the receiver 146// and is a transposed Dense or VecDense, with a non-unitary increment, Copy will 147// panic. 148// 149// See the Copier interface for more information. 150func (m *CDense) Copy(a CMatrix) (r, c int) { 151 r, c = a.Dims() 152 if a == m { 153 return r, c 154 } 155 r = min(r, m.mat.Rows) 156 c = min(c, m.mat.Cols) 157 if r == 0 || c == 0 { 158 return 0, 0 159 } 160 // TODO(btracey): Check for overlap when complex version exists. 161 // TODO(btracey): Add fast-paths. 162 for i := 0; i < r; i++ { 163 for j := 0; j < c; j++ { 164 m.set(i, j, a.At(i, j)) 165 } 166 } 167 return r, c 168} 169