suanPan
DenseMat.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (C) 2017-2022 Theodore Chang
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  ******************************************************************************/
29 #ifndef DENSEMAT_HPP
30 #define DENSEMAT_HPP
31 
32 #include "MetaMat.hpp"
33 
34 template<sp_d T> class DenseMat : public MetaMat<T> {
35  void init();
36 
37 protected:
38  podarray<int> pivot;
39  podarray<float> s_memory; // float storage used in mixed precision algorithm
40 
41  podarray<float> to_float();
42 
43  const T* const memory = nullptr;
44 
45 public:
47 
48  DenseMat(uword, uword, uword);
49  DenseMat(const DenseMat&);
50  DenseMat(DenseMat&&) noexcept;
51  DenseMat& operator=(const DenseMat&);
52  DenseMat& operator=(DenseMat&&) noexcept;
53  ~DenseMat() override;
54 
55  [[nodiscard]] bool is_empty() const override;
56  void zeros() override;
57 
58  [[nodiscard]] T max() const override;
59  [[nodiscard]] Col<T> diag() const override;
60 
61  const T* memptr() const override;
62  T* memptr() override;
63 
64  void operator+=(const shared_ptr<MetaMat<T>>&) override;
65  void operator-=(const shared_ptr<MetaMat<T>>&) override;
66 
67  void operator+=(const triplet_form<T, uword>&) override;
68  void operator-=(const triplet_form<T, uword>&) override;
69 
70  void operator*=(T) override;
71 
72  [[nodiscard]] int sign_det() const override;
73 };
74 
75 template<sp_d T> void DenseMat<T>::init() {
76  if(nullptr != memory) memory::release(access::rw(memory));
77  access::rw(memory) = is_empty() ? nullptr : memory::acquire<T>(this->n_elem);
78 }
79 
80 template<sp_d T> podarray<float> DenseMat<T>::to_float() {
81  podarray<float> f_memory(this->n_elem);
82 
83  suanpan_for(0llu, this->n_elem, [&](const uword I) { f_memory(I) = static_cast<float>(memory[I]); });
84 
85  return f_memory;
86 }
87 
88 template<sp_d T> DenseMat<T>::DenseMat(const uword in_rows, const uword in_cols, const uword in_elem)
89  : MetaMat<T>(in_rows, in_cols, in_elem) {
90  init();
92 }
93 
94 template<sp_d T> DenseMat<T>::DenseMat(const DenseMat& old_mat)
95  : MetaMat<T>(old_mat)
96  , pivot(old_mat.pivot)
97  , s_memory(old_mat.s_memory) {
98  init();
99  if(nullptr != old_mat.memory) std::copy(old_mat.memory, old_mat.memory + old_mat.n_elem, DenseMat<T>::memptr());
100 }
101 
102 template<sp_d T> DenseMat<T>::DenseMat(DenseMat&& old_mat) noexcept
103  : MetaMat<T>(std::move(old_mat))
104  , pivot(std::move(old_mat.pivot))
105  , s_memory(std::move(old_mat.s_memory)) {
106  access::rw(memory) = old_mat.memory;
107  access::rw(old_mat.memory) = nullptr;
108 }
109 
110 template<sp_d T> DenseMat<T>& DenseMat<T>::operator=(const DenseMat& old_mat) {
111  if(this == &old_mat) return *this;
112  MetaMat<T>::operator=(old_mat);
113  pivot = old_mat.pivot;
114  s_memory = old_mat.s_memory;
115  init();
116  if(nullptr != old_mat.memory) std::copy(old_mat.memory, old_mat.memory + old_mat.n_elem, memptr());
117  return *this;
118 }
119 
120 template<sp_d T> DenseMat<T>& DenseMat<T>::operator=(DenseMat&& old_mat) noexcept {
121  if(this == &old_mat) return *this;
122  MetaMat<T>::operator=(std::move(old_mat));
123  pivot = std::move(old_mat.pivot);
124  s_memory = std::move(old_mat.s_memory);
125  access::rw(memory) = old_mat.memory;
126  access::rw(old_mat.memory) = nullptr;
127  return *this;
128 }
129 
130 template<sp_d T> DenseMat<T>::~DenseMat() { if(nullptr != memory) memory::release(access::rw(memory)); }
131 
132 template<sp_d T> bool DenseMat<T>::is_empty() const { return 0 == this->n_elem; }
133 
134 template<sp_d T> void DenseMat<T>::zeros() {
135  arrayops::fill_zeros(memptr(), this->n_elem);
136  this->factored = false;
137 }
138 
139 template<sp_d T> T DenseMat<T>::max() const { return op_max::direct_max(memptr(), this->n_elem); }
140 
141 template<sp_d T> Col<T> DenseMat<T>::diag() const {
142  Col<T> diag_vec(std::min(this->n_rows, this->n_cols), fill::none);
143 
144  suanpan_for(0llu, diag_vec.n_elem, [&](const uword I) { diag_vec(I) = this->operator()(I, I); });
145 
146  return diag_vec;
147 }
148 
149 template<sp_d T> const T* DenseMat<T>::memptr() const { return memory; }
150 
151 template<sp_d T> T* DenseMat<T>::memptr() { return const_cast<T*>(memory); }
152 
153 template<sp_d T> void DenseMat<T>::operator+=(const shared_ptr<MetaMat<T>>& M) {
154  if(nullptr == M) return;
155  if(!M->triplet_mat.is_empty()) return this->operator+=(M->triplet_mat);
156  if(this->n_rows != M->n_rows || this->n_cols != M->n_cols || this->n_elem != M->n_elem) return;
157  if(nullptr == M->memptr()) return;
158  arrayops::inplace_plus(memptr(), M->memptr(), this->n_elem);
159  this->factored = false;
160 }
161 
162 template<sp_d T> void DenseMat<T>::operator-=(const shared_ptr<MetaMat<T>>& M) {
163  if(nullptr == M) return;
164  if(!M->triplet_mat.is_empty()) return this->operator-=(M->triplet_mat);
165  if(this->n_rows != M->n_rows || this->n_cols != M->n_cols || this->n_elem != M->n_elem) return;
166  if(nullptr == M->memptr()) return;
167  arrayops::inplace_minus(memptr(), M->memptr(), this->n_elem);
168  this->factored = false;
169 }
170 
171 template<sp_d T> void DenseMat<T>::operator+=(const triplet_form<T, uword>& M) {
172  if(this->n_rows != M.n_rows || this->n_cols != M.n_cols) return;
173 
174  const auto row = M.row_mem();
175  const auto col = M.col_mem();
176  const auto val = M.val_mem();
177  for(uword I = 0llu; I < M.n_elem; ++I) this->at(row[I], col[I]) += val[I];
178 }
179 
180 template<sp_d T> void DenseMat<T>::operator-=(const triplet_form<T, uword>& M) {
181  if(this->n_rows != M.n_rows || this->n_cols != M.n_cols) return;
182 
183  const auto row = M.row_mem();
184  const auto col = M.col_mem();
185  const auto val = M.val_mem();
186  for(uword I = 0llu; I < M.n_elem; ++I) this->at(row[I], col[I]) -= val[I];
187 }
188 
189 template<sp_d T> void DenseMat<T>::operator*=(const T value) { arrayops::inplace_mul(memptr(), value, this->n_elem); }
190 
191 template<sp_d T> int DenseMat<T>::sign_det() const {
192  if(IterativeSolver::NONE != this->setting.iterative_solver) throw invalid_argument("analysis requires the sign of determinant but iterative solver does not support it");
193  auto det_sign = 1;
194  for(unsigned I = 0; I < pivot.n_elem; ++I) if((this->operator()(I, I) < 0.) ^ (static_cast<int>(I) + 1 != pivot(I))) det_sign = -det_sign;
195  return det_sign;
196 }
197 
198 #endif
199 
A DenseMat class that holds matrices.
Definition: DenseMat.hpp:34
podarray< int > pivot
Definition: DenseMat.hpp:38
podarray< float > s_memory
Definition: DenseMat.hpp:39
const T *const memory
Definition: DenseMat.hpp:43
A MetaMat class that holds matrices.
Definition: MetaMat.hpp:39
MetaMat & operator=(const MetaMat &)=delete
const uword n_elem
Definition: MetaMat.hpp:50
Definition: triplet_form.hpp:62
podarray< float > to_float()
Definition: DenseMat.hpp:80
Col< T > diag() const override
Definition: DenseMat.hpp:141
const T * memptr() const override
Definition: DenseMat.hpp:149
void zeros() override
Definition: DenseMat.hpp:134
DenseMat & operator=(const DenseMat &)
Definition: DenseMat.hpp:110
T max() const override
Definition: DenseMat.hpp:139
void operator*=(T) override
Definition: DenseMat.hpp:189
bool is_empty() const override
Definition: DenseMat.hpp:132
int sign_det() const override
Definition: DenseMat.hpp:191
void operator+=(const shared_ptr< MetaMat< T >> &) override
Definition: DenseMat.hpp:153
DenseMat(uword, uword, uword)
Definition: DenseMat.hpp:88
~DenseMat() override
Definition: DenseMat.hpp:130
void operator-=(const shared_ptr< MetaMat< T >> &) override
Definition: DenseMat.hpp:162
const shared_ptr< MetaMat< T > > & operator+=(const shared_ptr< MetaMat< T >> &M, const shared_ptr< MetaMat< T >> &A)
Definition: operator_times.hpp:45
const shared_ptr< MetaMat< T > > & operator-=(const shared_ptr< MetaMat< T >> &M, const shared_ptr< MetaMat< T >> &A)
Definition: operator_times.hpp:86
concept sp_d
Definition: suanPan.h:227
void suanpan_for(const IT start, const IT end, F &&FN)
Definition: utility.h:24