tatami
C++ API for different matrix representations
Loading...
Searching...
No Matches
DenseMatrix.hpp
Go to the documentation of this file.
1#ifndef TATAMI_DENSE_MATRIX_H
2#define TATAMI_DENSE_MATRIX_H
3
4#include "../base/Matrix.hpp"
7#include "../utils/Index_to_container.hpp"
9
10#include <vector>
11#include <algorithm>
12#include <stdexcept>
13#include <utility>
14
15#include "sanisizer/sanisizer.hpp"
16
25namespace tatami {
26
30namespace DenseMatrix_internals {
31
32template<typename Value_, typename Index_, class Storage_>
33class PrimaryMyopicFullDense final : public MyopicDenseExtractor<Value_, Index_> {
34public:
35 PrimaryMyopicFullDense(const Storage_& storage, Index_ secondary) : my_storage(storage), my_secondary(secondary) {}
36
37 const Value_* fetch(Index_ i, Value_* buffer) {
38 auto offset = sanisizer::product_unsafe<decltype(my_storage.size())>(my_secondary, i);
39 if constexpr(has_data<Value_, Storage_>::value) {
40 return my_storage.data() + offset;
41 } else {
42 std::copy_n(my_storage.begin() + offset, my_secondary, buffer);
43 return buffer;
44 }
45 }
46
47private:
48 const Storage_& my_storage;
49 Index_ my_secondary;
50};
51
52template<typename Value_, typename Index_, class Storage_>
53class PrimaryMyopicBlockDense final : public MyopicDenseExtractor<Value_, Index_> {
54public:
55 PrimaryMyopicBlockDense(const Storage_& storage, Index_ secondary, Index_ block_start, Index_ block_length) :
56 my_storage(storage), my_secondary(secondary), my_block_start(block_start), my_block_length(block_length) {}
57
58 const Value_* fetch(Index_ i, Value_* buffer) {
59 auto offset = sanisizer::nd_offset<decltype(my_storage.size())>(my_block_start, my_secondary, i);
60 if constexpr(has_data<Value_, Storage_>::value) {
61 return my_storage.data() + offset;
62 } else {
63 std::copy_n(my_storage.begin() + offset, my_block_length, buffer);
64 return buffer;
65 }
66 }
67
68private:
69 const Storage_& my_storage;
70 Index_ my_secondary;
71 Index_ my_block_start, my_block_length;
72};
73
74template<typename Value_, typename Index_, class Storage_>
75class PrimaryMyopicIndexDense final : public MyopicDenseExtractor<Value_, Index_> {
76public:
77 PrimaryMyopicIndexDense(const Storage_& storage, Index_ secondary, VectorPtr<Index_> indices_ptr) :
78 my_storage(storage), my_secondary(secondary), my_indices_ptr(std::move(indices_ptr)) {}
79
80 const Value_* fetch(Index_ i, Value_* buffer) {
81 const auto& indices = *my_indices_ptr;
82 for (decltype(indices.size()) x = 0, end = indices.size(); x < end; ++x) {
83 buffer[x] = my_storage[sanisizer::nd_offset<decltype(my_storage.size())>(indices[x], my_secondary, i)];
84 }
85 return buffer;
86 }
87
88private:
89 const Storage_& my_storage;
90 Index_ my_secondary;
91 VectorPtr<Index_> my_indices_ptr;
92};
93
94template<typename Value_, typename Index_, class Storage_>
95class SecondaryMyopicFullDense final : public MyopicDenseExtractor<Value_, Index_> {
96public:
97 SecondaryMyopicFullDense(const Storage_& storage, Index_ secondary, Index_ primary) :
98 my_storage(storage), my_secondary(secondary), my_primary(primary) {}
99
100 const Value_* fetch(Index_ i, Value_* buffer) {
101 for (decltype(my_primary) x = 0; x < my_primary; ++x) {
102 buffer[x] = my_storage[sanisizer::nd_offset<decltype(my_storage.size())>(i, my_secondary, x)];
103 }
104 return buffer;
105 }
106
107private:
108 const Storage_& my_storage;
109 Index_ my_secondary;
110 Index_ my_primary;
111};
112
113template<typename Value_, typename Index_, class Storage_>
114class SecondaryMyopicBlockDense final : public MyopicDenseExtractor<Value_, Index_> {
115public:
116 SecondaryMyopicBlockDense(const Storage_& storage, Index_ secondary, Index_ block_start, Index_ block_length) :
117 my_storage(storage), my_secondary(secondary), my_block_start(block_start), my_block_length(block_length) {}
118
119 const Value_* fetch(Index_ i, Value_* buffer) {
120 for (decltype(my_block_length) x = 0; x < my_block_length; ++x) {
121 buffer[x] = my_storage[sanisizer::nd_offset<decltype(my_storage.size())>(i, my_secondary, my_block_start + x)];
122 }
123 return buffer;
124 }
125
126private:
127 const Storage_& my_storage;
128 Index_ my_secondary;
129 Index_ my_block_start;
130 Index_ my_block_length;
131};
132
133template<typename Value_, typename Index_, class Storage_>
134class SecondaryMyopicIndexDense final : public MyopicDenseExtractor<Value_, Index_> {
135public:
136 SecondaryMyopicIndexDense(const Storage_& storage, Index_ secondary, VectorPtr<Index_> indices_ptr) :
137 my_storage(storage), my_secondary(secondary), my_indices_ptr(std::move(indices_ptr)) {}
138
139 const Value_* fetch(Index_ i, Value_* buffer) {
140 const auto& indices = *my_indices_ptr;
141 for (decltype(indices.size()) x = 0, end = indices.size(); x < end; ++x) {
142 buffer[x] = my_storage[sanisizer::nd_offset<decltype(my_storage.size())>(i, my_secondary, indices[x])];
143 }
144 return buffer;
145 }
146
147private:
148 const Storage_& my_storage;
149 Index_ my_secondary;
150 VectorPtr<Index_> my_indices_ptr;
151};
152
153}
168template<typename Value_, typename Index_, class Storage_>
169class DenseMatrix : public Matrix<Value_, Index_> {
170public:
178 DenseMatrix(Index_ nrow, Index_ ncol, Storage_ values, bool row_major) : my_nrow(nrow), my_ncol(ncol), my_values(std::move(values)), my_row_major(row_major) {
179 auto nvalues = my_values.size();
180 if (my_nrow == 0) {
181 if (nvalues != 0) {
182 throw std::runtime_error("length of 'values' should be equal to product of 'nrows' and 'ncols'");
183 }
184 } else if (!safe_non_negative_equal(nvalues / my_nrow, my_ncol) || nvalues % my_nrow != 0) { // using division instead of 'my_nrow * my_ncol == nvalues' as the product might overflow.
185 throw std::runtime_error("length of 'values' should be equal to product of 'nrows' and 'ncols'");
186 }
187 }
188
189private:
190 Index_ my_nrow, my_ncol;
191 Storage_ my_values;
192 bool my_row_major;
193
194public:
195 Index_ nrow() const { return my_nrow; }
196
197 Index_ ncol() const { return my_ncol; }
198
199 bool prefer_rows() const { return my_row_major; }
200
201 bool uses_oracle(bool) const { return false; }
202
203 bool is_sparse() const { return false; }
204
205 double is_sparse_proportion() const { return 0; }
206
207 double prefer_rows_proportion() const { return static_cast<double>(my_row_major); }
208
209 using Matrix<Value_, Index_>::dense;
210
211 using Matrix<Value_, Index_>::sparse;
212
213private:
214 Index_ primary() const {
215 if (my_row_major) {
216 return my_nrow;
217 } else {
218 return my_ncol;
219 }
220 }
221
222 Index_ secondary() const {
223 if (my_row_major) {
224 return my_ncol;
225 } else {
226 return my_nrow;
227 }
228 }
229
230 /*****************************
231 ******* Dense myopic ********
232 *****************************/
233public:
234 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, const Options&) const {
235 if (my_row_major == row) {
236 return std::make_unique<DenseMatrix_internals::PrimaryMyopicFullDense<Value_, Index_, Storage_> >(my_values, secondary());
237 } else {
238 return std::make_unique<DenseMatrix_internals::SecondaryMyopicFullDense<Value_, Index_, Storage_> >(my_values, secondary(), primary());
239 }
240 }
241
242 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, Index_ block_start, Index_ block_length, const Options&) const {
243 if (my_row_major == row) {
244 return std::make_unique<DenseMatrix_internals::PrimaryMyopicBlockDense<Value_, Index_, Storage_> >(my_values, secondary(), block_start, block_length);
245 } else {
246 return std::make_unique<DenseMatrix_internals::SecondaryMyopicBlockDense<Value_, Index_, Storage_> >(my_values, secondary(), block_start, block_length);
247 }
248 }
249
250 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, VectorPtr<Index_> indices_ptr, const Options&) const {
251 if (my_row_major == row) {
252 return std::make_unique<DenseMatrix_internals::PrimaryMyopicIndexDense<Value_, Index_, Storage_> >(my_values, secondary(), std::move(indices_ptr));
253 } else {
254 return std::make_unique<DenseMatrix_internals::SecondaryMyopicIndexDense<Value_, Index_, Storage_> >(my_values, secondary(), std::move(indices_ptr));
255 }
256 }
257
258 /******************************
259 ******* Sparse myopic ********
260 ******************************/
261public:
262 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, const Options& opt) const {
263 return std::make_unique<FullSparsifiedWrapper<false, Value_, Index_> >(dense(row, opt), (row ? my_ncol : my_nrow), opt);
264 }
265
266 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
267 return std::make_unique<BlockSparsifiedWrapper<false, Value_, Index_> >(dense(row, block_start, block_length, opt), block_start, block_length, opt);
268 }
269
270 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, VectorPtr<Index_> indices_ptr, const Options& opt) const {
271 auto ptr = dense(row, indices_ptr, opt);
272 return std::make_unique<IndexSparsifiedWrapper<false, Value_, Index_> >(std::move(ptr), std::move(indices_ptr), opt);
273 }
274
275 /*******************************
276 ******* Dense oracular ********
277 *******************************/
278public:
279 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
280 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, opt));
281 }
282
283 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, Index_ block_start, Index_ block_end, const Options& opt) const {
284 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, block_start, block_end, opt));
285 }
286
287 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
288 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, std::move(indices_ptr), opt));
289 }
290
291 /********************************
292 ******* Sparse oracular ********
293 ********************************/
294public:
295 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
296 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, opt));
297 }
298
299 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, Index_ block_start, Index_ block_end, const Options& opt) const {
300 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, block_start, block_end, opt));
301 }
302
303 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
304 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, std::move(indices_ptr), opt));
305 }
306};
307
313template<typename Value_, typename Index_, class Storage_ = std::vector<Value_> >
314class DenseColumnMatrix final : public DenseMatrix<Value_, Index_, Storage_> {
315public:
321 DenseColumnMatrix(Index_ nrow, Index_ ncol, Storage_ values) : DenseMatrix<Value_, Index_, Storage_>(nrow, ncol, std::move(values), false) {}
322};
323
329template<typename Value_, typename Index_, class Storage_ = std::vector<Value_> >
330class DenseRowMatrix final : public DenseMatrix<Value_, Index_, Storage_> {
331public:
337 DenseRowMatrix(Index_ nrow, Index_ ncol, Storage_ values) : DenseMatrix<Value_, Index_, Storage_>(nrow, ncol, std::move(values), true) {}
338};
339
340}
341
342#endif
Virtual class for a matrix of some numeric type.
Mimic the oracle-aware extractor interface.
Wrapper classes for sparse extraction from a dense tatami::Matrix.
Dense column-major matrix.
Definition DenseMatrix.hpp:314
DenseColumnMatrix(Index_ nrow, Index_ ncol, Storage_ values)
Definition DenseMatrix.hpp:321
Dense matrix representation.
Definition DenseMatrix.hpp:169
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, const Options &) const
Definition DenseMatrix.hpp:234
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, Index_ block_start, Index_ block_end, const Options &opt) const
Definition DenseMatrix.hpp:299
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const
Definition DenseMatrix.hpp:262
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DenseMatrix.hpp:279
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, VectorPtr< Index_ > indices_ptr, const Options &) const
Definition DenseMatrix.hpp:250
DenseMatrix(Index_ nrow, Index_ ncol, Storage_ values, bool row_major)
Definition DenseMatrix.hpp:178
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DenseMatrix.hpp:287
double prefer_rows_proportion() const
Definition DenseMatrix.hpp:207
bool prefer_rows() const
Definition DenseMatrix.hpp:199
bool is_sparse() const
Definition DenseMatrix.hpp:203
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DenseMatrix.hpp:303
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DenseMatrix.hpp:270
bool uses_oracle(bool) const
Definition DenseMatrix.hpp:201
double is_sparse_proportion() const
Definition DenseMatrix.hpp:205
Index_ nrow() const
Definition DenseMatrix.hpp:195
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, Index_ block_start, Index_ block_length, const Options &) const
Definition DenseMatrix.hpp:242
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DenseMatrix.hpp:266
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, Index_ block_start, Index_ block_end, const Options &opt) const
Definition DenseMatrix.hpp:283
Index_ ncol() const
Definition DenseMatrix.hpp:197
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DenseMatrix.hpp:295
Dense row-major matrix.
Definition DenseMatrix.hpp:330
DenseRowMatrix(Index_ nrow, Index_ ncol, Storage_ values)
Definition DenseMatrix.hpp:337
Virtual class for a matrix.
Definition Matrix.hpp:59
Predict future access requests on the target dimension.
Definition Oracle.hpp:29
Compile-time checks for the data() method.
Flexible representations for matrix data.
Definition Extractor.hpp:15
std::shared_ptr< const std::vector< Index_ > > VectorPtr
Definition Matrix.hpp:26
Options for accessing data from a Matrix instance.
Definition Options.hpp:30