30namespace internal::dense_matrix {
37 return std::conj(value);
46 DenseMatrix(
int rows,
int columns,
const T& initial_value = T{})
47 : data_(static_cast<std::size_t>(require_dimension(rows,
"rows")) *
48 static_cast<std::size_t>(require_dimension(columns,
"columns")),
51 , columns_(columns) {}
54 DenseMatrix(
int rows,
int columns, std::vector<T> column_major_data)
55 : data_(std::move(column_major_data))
56 , rows_(require_dimension(rows,
"rows"))
57 , columns_(require_dimension(columns,
"columns")) {
58 if (data_.size() != number_of_elements()) {
59 throw std::invalid_argument(
60 "DenseMatrix: a " + std::to_string(rows) +
" x " + std::to_string(columns) +
61 " matrix holds " + std::to_string(number_of_elements()) +
" elements, not the " +
62 std::to_string(data_.size()) +
" given");
68 for (
int index = 0; index < dimension; index++) {
69 matrix(index, index) = T{1};
74 [[nodiscard]]
int rows()
const {
81 return static_cast<std::size_t
>(rows_) *
static_cast<std::size_t
>(columns_);
83 [[nodiscard]]
bool empty()
const {
88 return data_[index_of(row, column)];
90 [[nodiscard]]
const T&
operator()(
int row,
int column)
const {
91 return data_[index_of(row, column)];
98 [[nodiscard]]
const T*
data()
const {
102 [[nodiscard]]
const std::vector<T>&
raw()
const {
109 for (
int column = 0; column < columns_; column++) {
110 for (
int row = 0; row < rows_; row++) {
111 result(column, row) = internal::dense_matrix::conjugate((*
this)(row, column));
120 for (
const T& value : data_) {
121 total += std::norm(value);
129 for (T& value : result.data_) {
136 template <
typename Factor>
138 require_same_shape(other,
"add_scaled");
139 for (std::size_t index = 0; index < data_.size(); index++) {
140 data_[index] += factor * other.data_[index];
152 require_same_shape(other,
"real_inner_product");
154 for (std::size_t index = 0; index < data_.size(); index++) {
156 std::real(internal::dense_matrix::conjugate(data_[index]) * other.data_[index]);
163 const std::vector<int>& column_indices)
const {
165 static_cast<int>(row_indices.size()),
static_cast<int>(column_indices.size()), T{});
166 for (std::size_t column = 0; column < column_indices.size(); column++) {
167 for (std::size_t row = 0; row < row_indices.size(); row++) {
168 result(
static_cast<int>(row),
static_cast<int>(column)) =
169 (*this)(row_indices[row], column_indices[column]);
176 template <
typename Factor>
178 require_count(factors.size(), rows_,
"row");
180 for (
int column = 0; column < columns_; column++) {
181 for (
int row = 0; row < rows_; row++) {
182 result(row, column) *= factors[
static_cast<std::size_t
>(row)];
189 template <
typename Factor>
191 require_count(factors.size(), columns_,
"column");
193 for (
int column = 0; column < columns_; column++) {
194 for (
int row = 0; row < rows_; row++) {
195 result(row, column) *= factors[
static_cast<std::size_t
>(column)];
202 return rows_ == other.rows_ && columns_ == other.columns_ && data_ == other.data_;
205 return !(*
this == other);
209 [[nodiscard]] std::size_t index_of(
int row,
int column)
const {
210 if (row < 0 || row >= rows_ || column < 0 || column >= columns_) {
211 throw std::out_of_range(
"DenseMatrix: element (" + std::to_string(row) +
", " +
212 std::to_string(column) +
") is outside a " +
213 std::to_string(rows_) +
" x " + std::to_string(columns_) +
216 return static_cast<std::size_t
>(column) *
static_cast<std::size_t
>(rows_) +
217 static_cast<std::size_t
>(row);
220 [[nodiscard]]
static int require_dimension(
int value,
const char* name) {
222 throw std::invalid_argument(
"DenseMatrix: the number of " + std::string(name) +
223 " cannot be negative, got " + std::to_string(value));
228 void require_same_shape(
const DenseMatrix& other,
const char* operation)
const {
229 if (rows_ != other.rows_ || columns_ != other.columns_) {
230 throw std::invalid_argument(
231 "DenseMatrix::" + std::string(operation) +
": a " + std::to_string(rows_) +
" x " +
232 std::to_string(columns_) +
" matrix and a " + std::to_string(other.rows_) +
" x " +
233 std::to_string(other.columns_) +
" one have different shapes");
237 static void require_count(std::size_t given,
int wanted,
const char* axis) {
238 if (given !=
static_cast<std::size_t
>(wanted)) {
239 throw std::invalid_argument(
"DenseMatrix: one factor per " + std::string(axis) +
240 " is required, " + std::to_string(wanted) +
241 " of them, not " + std::to_string(given));
245 std::vector<T> data_;
DenseMatrix scaled_columns(const std::vector< Factor > &factors) const
this * diag(factors): column j scaled by factors[j], which needs one factor per column.
bool operator!=(const DenseMatrix &other) const
Real frobenius_norm_squared() const
The sum of every element's squared modulus.
T & operator()(int row, int column)
bool operator==(const DenseMatrix &other) const
DenseMatrix submatrix(const std::vector< int > &row_indices, const std::vector< int > &column_indices) const
The rows and columns named, in the order named; an index outside the matrix is refused.
const std::vector< T > & raw() const
Read-only: a caller that could resize the buffer could break rows() x columns().
DenseMatrix & add_scaled(const Factor &factor, const DenseMatrix &other)
this += factor * other, element by element; the two shapes must agree.
DenseMatrix(int rows, int columns, std::vector< T > column_major_data)
Adopts a column-major buffer; refuses one whose size is not rows * columns.
T * data()
The column-major buffer: with rows() it is the (pointer, leading dimension) BLAS takes.
DenseMatrix(int rows, int columns, const T &initial_value=T{})
std::size_t number_of_elements() const
DenseMatrix scaled(const Factor &factor) const
factor * this, element by element.
DenseMatrix scaled_rows(const std::vector< Factor > &factors) const
diag(factors) * this: row i scaled by factors[i], which needs one factor per row.
Real real_inner_product(const DenseMatrix &other) const
const T & operator()(int row, int column) const
static DenseMatrix identity(int dimension)
DenseMatrix adjoint() const
The conjugate transpose, columns x rows.
Real conjugate(Real value)
std::complex< double > Complex