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"
6#include "../utils/has_data.hpp"
7#include "../utils/PseudoOracularExtractor.hpp"
8
9#include <vector>
10#include <algorithm>
11#include <stdexcept>
12
21namespace tatami {
22
26namespace DenseMatrix_internals {
27
28template<typename Value_, typename Index_, class Storage_>
29class PrimaryMyopicFullDense : public MyopicDenseExtractor<Value_, Index_> {
30public:
31 PrimaryMyopicFullDense(const Storage_& storage, size_t secondary) : my_storage(storage), my_secondary(secondary) {}
32
33 const Value_* fetch(Index_ i, Value_* buffer) {
34 size_t offset = static_cast<size_t>(i) * my_secondary; // cast to size_t to avoid overflow of 'Index_'.
35 if constexpr(has_data<Value_, Storage_>::value) {
36 return my_storage.data() + offset;
37 } else {
38 std::copy_n(my_storage.begin() + offset, my_secondary, buffer);
39 return buffer;
40 }
41 }
42
43private:
44 const Storage_& my_storage;
45 size_t my_secondary;
46};
47
48template<typename Value_, typename Index_, class Storage_>
49class PrimaryMyopicBlockDense : public MyopicDenseExtractor<Value_, Index_> {
50public:
51 PrimaryMyopicBlockDense(const Storage_& storage, size_t secondary, Index_ block_start, Index_ block_length) :
52 my_storage(storage), my_secondary(secondary), my_block_start(block_start), my_block_length(block_length) {}
53
54 const Value_* fetch(Index_ i, Value_* buffer) {
55 size_t offset = static_cast<size_t>(i) * my_secondary + my_block_start; // cast to size_t to avoid overflow.
56 if constexpr(has_data<Value_, Storage_>::value) {
57 return my_storage.data() + offset;
58 } else {
59 std::copy_n(my_storage.begin() + offset, my_block_length, buffer);
60 return buffer;
61 }
62 }
63
64private:
65 const Storage_& my_storage;
66 size_t my_secondary;
67 size_t my_block_start, my_block_length;
68};
69
70template<typename Value_, typename Index_, class Storage_>
71class PrimaryMyopicIndexDense : public MyopicDenseExtractor<Value_, Index_> {
72public:
73 PrimaryMyopicIndexDense(const Storage_& storage, size_t secondary, VectorPtr<Index_> indices_ptr) :
74 my_storage(storage), my_secondary(secondary), my_indices_ptr(std::move(indices_ptr)) {}
75
76 const Value_* fetch(Index_ i, Value_* buffer) {
77 auto copy = buffer;
78 size_t offset = static_cast<size_t>(i) * my_secondary; // cast to size_t avoid overflow.
79 for (auto x : *my_indices_ptr) {
80 *copy = my_storage[offset + static_cast<size_t>(x)]; // more casting for overflow protection.
81 ++copy;
82 }
83 return buffer;
84 }
85
86private:
87 const Storage_& my_storage;
88 size_t my_secondary;
89 VectorPtr<Index_> my_indices_ptr;
90};
91
92template<typename Value_, typename Index_, class Storage_>
93class SecondaryMyopicFullDense : public MyopicDenseExtractor<Value_, Index_> {
94public:
95 SecondaryMyopicFullDense(const Storage_& storage, Index_ secondary, Index_ primary) :
96 my_storage(storage), my_secondary(secondary), my_primary(primary) {}
97
98 const Value_* fetch(Index_ i, Value_* buffer) {
99 size_t offset = i; // use size_t to avoid overflow.
100 auto copy = buffer;
101 for (Index_ x = 0; x < my_primary; ++x, ++copy, offset += my_secondary) {
102 *copy = my_storage[offset];
103 }
104 return buffer;
105 }
106
107private:
108 const Storage_& my_storage;
109 size_t my_secondary;
110 Index_ my_primary;
111};
112
113template<typename Value_, typename Index_, class Storage_>
114class SecondaryMyopicBlockDense : 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 size_t offset = my_block_start * my_secondary + static_cast<size_t>(i); // cast to avoid overflow.
121 auto copy = buffer;
122 for (Index_ x = 0; x < my_block_length; ++x, ++copy, offset += my_secondary) {
123 *copy = my_storage[offset];
124 }
125 return buffer;
126 }
127
128private:
129 const Storage_& my_storage;
130 size_t my_secondary;
131 size_t my_block_start;
132 Index_ my_block_length;
133};
134
135template<typename Value_, typename Index_, class Storage_>
136class SecondaryMyopicIndexDense : public MyopicDenseExtractor<Value_, Index_> {
137public:
138 SecondaryMyopicIndexDense(const Storage_& storage, Index_ secondary, VectorPtr<Index_> indices_ptr) :
139 my_storage(storage), my_secondary(secondary), my_indices_ptr(std::move(indices_ptr)) {}
140
141 const Value_* fetch(Index_ i, Value_* buffer) {
142 auto copy = buffer;
143 size_t offset = static_cast<size_t>(i); // cast to avoid overflow.
144 for (auto x : *my_indices_ptr) {
145 *copy = my_storage[static_cast<size_t>(x) * my_secondary + offset]; // more casting to avoid overflow.
146 ++copy;
147 }
148 return buffer;
149 }
150
151private:
152 const Storage_& my_storage;
153 size_t my_secondary;
154 VectorPtr<Index_> my_indices_ptr;
155};
156
157}
172template<typename Value_, typename Index_, class Storage_ = std::vector<Value_> >
173class DenseMatrix : public Matrix<Value_, Index_> {
174public:
182 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) {
183 if (static_cast<size_t>(my_nrow) * static_cast<size_t>(my_ncol) != my_values.size()) { // cast to size_t is deliberate to avoid overflow on Index_ on product.
184 throw std::runtime_error("length of 'values' should be equal to product of 'nrows' and 'ncols'");
185 }
186 }
187
188private:
189 Index_ my_nrow, my_ncol;
190 Storage_ my_values;
191 bool my_row_major;
192
193public:
194 Index_ nrow() const { return my_nrow; }
195
196 Index_ ncol() const { return my_ncol; }
197
198 bool prefer_rows() const { return my_row_major; }
199
200 bool uses_oracle(bool) const { return false; }
201
202 bool is_sparse() const { return false; }
203
204 double is_sparse_proportion() const { return 0; }
205
206 double prefer_rows_proportion() const { return static_cast<double>(my_row_major); }
207
209
211
212private:
213 Index_ primary() const {
214 if (my_row_major) {
215 return my_nrow;
216 } else {
217 return my_ncol;
218 }
219 }
220
221 Index_ secondary() const {
222 if (my_row_major) {
223 return my_ncol;
224 } else {
225 return my_nrow;
226 }
227 }
228
229 /*****************************
230 ******* Dense myopic ********
231 *****************************/
232public:
233 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, const Options&) const {
234 if (my_row_major == row) {
235 return std::make_unique<DenseMatrix_internals::PrimaryMyopicFullDense<Value_, Index_, Storage_> >(my_values, secondary());
236 } else {
237 return std::make_unique<DenseMatrix_internals::SecondaryMyopicFullDense<Value_, Index_, Storage_> >(my_values, secondary(), primary());
238 }
239 }
240
241 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, Index_ block_start, Index_ block_length, const Options&) const {
242 if (my_row_major == row) {
243 return std::make_unique<DenseMatrix_internals::PrimaryMyopicBlockDense<Value_, Index_, Storage_> >(my_values, secondary(), block_start, block_length);
244 } else {
245 return std::make_unique<DenseMatrix_internals::SecondaryMyopicBlockDense<Value_, Index_, Storage_> >(my_values, secondary(), block_start, block_length);
246 }
247 }
248
249 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, VectorPtr<Index_> indices_ptr, const Options&) const {
250 if (my_row_major == row) {
251 return std::make_unique<DenseMatrix_internals::PrimaryMyopicIndexDense<Value_, Index_, Storage_> >(my_values, secondary(), std::move(indices_ptr));
252 } else {
253 return std::make_unique<DenseMatrix_internals::SecondaryMyopicIndexDense<Value_, Index_, Storage_> >(my_values, secondary(), std::move(indices_ptr));
254 }
255 }
256
257 /******************************
258 ******* Sparse myopic ********
259 ******************************/
260public:
261 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, const Options& opt) const {
262 return std::make_unique<FullSparsifiedWrapper<false, Value_, Index_> >(dense(row, opt), (row ? my_ncol : my_nrow), opt);
263 }
264
265 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
266 return std::make_unique<BlockSparsifiedWrapper<false, Value_, Index_> >(dense(row, block_start, block_length, opt), block_start, block_length, opt);
267 }
268
269 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, VectorPtr<Index_> indices_ptr, const Options& opt) const {
270 auto ptr = dense(row, indices_ptr, opt);
271 return std::make_unique<IndexSparsifiedWrapper<false, Value_, Index_> >(std::move(ptr), std::move(indices_ptr), opt);
272 }
273
274 /*******************************
275 ******* Dense oracular ********
276 *******************************/
277public:
278 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
279 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, opt));
280 }
281
282 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 {
283 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, block_start, block_end, opt));
284 }
285
286 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
287 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, std::move(indices_ptr), opt));
288 }
289
290 /********************************
291 ******* Sparse oracular ********
292 ********************************/
293public:
294 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
295 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, opt));
296 }
297
298 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 {
299 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, block_start, block_end, opt));
300 }
301
302 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
303 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, std::move(indices_ptr), opt));
304 }
305};
306
312template<typename Value_, typename Index_, class Storage_ = std::vector<Value_> >
313class DenseColumnMatrix : public DenseMatrix<Value_, Index_, Storage_> {
314public:
321};
322
328template<typename Value_, typename Index_, class Storage_ = std::vector<Value_> >
329class DenseRowMatrix : public DenseMatrix<Value_, Index_, Storage_> {
330public:
337};
338
339}
340
341#endif
Wrapper classes for sparse extraction from a dense tatami::Matrix.
Dense column-major matrix.
Definition DenseMatrix.hpp:313
DenseColumnMatrix(Index_ nrow, Index_ ncol, Storage_ values)
Definition DenseMatrix.hpp:320
Dense matrix representation.
Definition DenseMatrix.hpp:173
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, const Options &) const
Definition DenseMatrix.hpp:233
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:298
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const
Definition DenseMatrix.hpp:261
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DenseMatrix.hpp:278
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, VectorPtr< Index_ > indices_ptr, const Options &) const
Definition DenseMatrix.hpp:249
DenseMatrix(Index_ nrow, Index_ ncol, Storage_ values, bool row_major)
Definition DenseMatrix.hpp:182
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:286
double prefer_rows_proportion() const
Definition DenseMatrix.hpp:206
bool prefer_rows() const
Definition DenseMatrix.hpp:198
bool is_sparse() const
Definition DenseMatrix.hpp:202
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:302
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DenseMatrix.hpp:269
bool uses_oracle(bool) const
Definition DenseMatrix.hpp:200
double is_sparse_proportion() const
Definition DenseMatrix.hpp:204
Index_ nrow() const
Definition DenseMatrix.hpp:194
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, Index_ block_start, Index_ block_length, const Options &) const
Definition DenseMatrix.hpp:241
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DenseMatrix.hpp:265
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:282
Index_ ncol() const
Definition DenseMatrix.hpp:196
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DenseMatrix.hpp:294
Dense row-major matrix.
Definition DenseMatrix.hpp:329
DenseRowMatrix(Index_ nrow, Index_ ncol, Storage_ values)
Definition DenseMatrix.hpp:336
Virtual class for a matrix.
Definition Matrix.hpp:59
Predict future access requests on the target dimension.
Definition Oracle.hpp:21
Flexible representations for matrix data.
Definition Extractor.hpp:15
std::shared_ptr< const std::vector< Index_ > > VectorPtr
Definition Matrix.hpp:26
auto consecutive_extractor(const Matrix< Value_, Index_ > *mat, bool row, Index_ iter_start, Index_ iter_length, Args_ &&... args)
Definition consecutive_extractor.hpp:35
Options for accessing data from a Matrix instance.
Definition Options.hpp:30