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.
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 size_t offset = static_cast<size_t>(i) * my_secondary; // cast to size_t to avoid overflow.
78 const auto& indices = *my_indices_ptr;
79 for (size_t x = 0, end = indices.size(); x < end; ++x) {
80 buffer[x] = my_storage[offset + static_cast<size_t>(indices[x])]; // more casting for overflow protection.
81 }
82 return buffer;
83 }
84
85private:
86 const Storage_& my_storage;
87 size_t my_secondary;
88 VectorPtr<Index_> my_indices_ptr;
89};
90
91template<typename Value_, typename Index_, class Storage_>
92class SecondaryMyopicFullDense : public MyopicDenseExtractor<Value_, Index_> {
93public:
94 SecondaryMyopicFullDense(const Storage_& storage, Index_ secondary, Index_ primary) :
95 my_storage(storage), my_secondary(secondary), my_primary(primary) {}
96
97 const Value_* fetch(Index_ i, Value_* buffer) {
98 for (size_t x = 0; x < my_primary; ++x) {
99 buffer[x] = my_storage[x * my_secondary + static_cast<size_t>(i)]; // cast to size_t to avoid overflow.
100 }
101 return buffer;
102 }
103
104private:
105 const Storage_& my_storage;
106 size_t my_secondary;
107 size_t my_primary;
108};
109
110template<typename Value_, typename Index_, class Storage_>
111class SecondaryMyopicBlockDense : public MyopicDenseExtractor<Value_, Index_> {
112public:
113 SecondaryMyopicBlockDense(const Storage_& storage, Index_ secondary, Index_ block_start, Index_ block_length) :
114 my_storage(storage), my_secondary(secondary), my_block_start(block_start), my_block_length(block_length) {}
115
116 const Value_* fetch(Index_ i, Value_* buffer) {
117 size_t offset = my_block_start * my_secondary + static_cast<size_t>(i); // cast to avoid overflow.
118 for (size_t x = 0; x < my_block_length; ++x) {
119 buffer[x] = my_storage[x * my_secondary + offset];
120 }
121 return buffer;
122 }
123
124private:
125 const Storage_& my_storage;
126 size_t my_secondary;
127 size_t my_block_start;
128 size_t my_block_length;
129};
130
131template<typename Value_, typename Index_, class Storage_>
132class SecondaryMyopicIndexDense : public MyopicDenseExtractor<Value_, Index_> {
133public:
134 SecondaryMyopicIndexDense(const Storage_& storage, Index_ secondary, VectorPtr<Index_> indices_ptr) :
135 my_storage(storage), my_secondary(secondary), my_indices_ptr(std::move(indices_ptr)) {}
136
137 const Value_* fetch(Index_ i, Value_* buffer) {
138 size_t offset = i;
139 const auto& indices = *my_indices_ptr;
140 for (size_t x = 0, end = indices.size(); x < end; ++x) {
141 buffer[x] = my_storage[static_cast<size_t>(indices[x]) * my_secondary + offset]; // casting to avoid overflow.
142 }
143 return buffer;
144 }
145
146private:
147 const Storage_& my_storage;
148 size_t my_secondary;
149 VectorPtr<Index_> my_indices_ptr;
150};
151
152}
167template<typename Value_, typename Index_, class Storage_ = std::vector<Value_> >
168class DenseMatrix : public Matrix<Value_, Index_> {
169public:
177 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) {
178 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.
179 throw std::runtime_error("length of 'values' should be equal to product of 'nrows' and 'ncols'");
180 }
181 }
182
183private:
184 Index_ my_nrow, my_ncol;
185 Storage_ my_values;
186 bool my_row_major;
187
188public:
189 Index_ nrow() const { return my_nrow; }
190
191 Index_ ncol() const { return my_ncol; }
192
193 bool prefer_rows() const { return my_row_major; }
194
195 bool uses_oracle(bool) const { return false; }
196
197 bool is_sparse() const { return false; }
198
199 double is_sparse_proportion() const { return 0; }
200
201 double prefer_rows_proportion() const { return static_cast<double>(my_row_major); }
202
204
206
207private:
208 Index_ primary() const {
209 if (my_row_major) {
210 return my_nrow;
211 } else {
212 return my_ncol;
213 }
214 }
215
216 Index_ secondary() const {
217 if (my_row_major) {
218 return my_ncol;
219 } else {
220 return my_nrow;
221 }
222 }
223
224 /*****************************
225 ******* Dense myopic ********
226 *****************************/
227public:
228 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, const Options&) const {
229 if (my_row_major == row) {
230 return std::make_unique<DenseMatrix_internals::PrimaryMyopicFullDense<Value_, Index_, Storage_> >(my_values, secondary());
231 } else {
232 return std::make_unique<DenseMatrix_internals::SecondaryMyopicFullDense<Value_, Index_, Storage_> >(my_values, secondary(), primary());
233 }
234 }
235
236 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, Index_ block_start, Index_ block_length, const Options&) const {
237 if (my_row_major == row) {
238 return std::make_unique<DenseMatrix_internals::PrimaryMyopicBlockDense<Value_, Index_, Storage_> >(my_values, secondary(), block_start, block_length);
239 } else {
240 return std::make_unique<DenseMatrix_internals::SecondaryMyopicBlockDense<Value_, Index_, Storage_> >(my_values, secondary(), block_start, block_length);
241 }
242 }
243
244 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, VectorPtr<Index_> indices_ptr, const Options&) const {
245 if (my_row_major == row) {
246 return std::make_unique<DenseMatrix_internals::PrimaryMyopicIndexDense<Value_, Index_, Storage_> >(my_values, secondary(), std::move(indices_ptr));
247 } else {
248 return std::make_unique<DenseMatrix_internals::SecondaryMyopicIndexDense<Value_, Index_, Storage_> >(my_values, secondary(), std::move(indices_ptr));
249 }
250 }
251
252 /******************************
253 ******* Sparse myopic ********
254 ******************************/
255public:
256 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, const Options& opt) const {
257 return std::make_unique<FullSparsifiedWrapper<false, Value_, Index_> >(dense(row, opt), (row ? my_ncol : my_nrow), opt);
258 }
259
260 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
261 return std::make_unique<BlockSparsifiedWrapper<false, Value_, Index_> >(dense(row, block_start, block_length, opt), block_start, block_length, opt);
262 }
263
264 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, VectorPtr<Index_> indices_ptr, const Options& opt) const {
265 auto ptr = dense(row, indices_ptr, opt);
266 return std::make_unique<IndexSparsifiedWrapper<false, Value_, Index_> >(std::move(ptr), std::move(indices_ptr), opt);
267 }
268
269 /*******************************
270 ******* Dense oracular ********
271 *******************************/
272public:
273 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
274 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, opt));
275 }
276
277 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 {
278 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, block_start, block_end, opt));
279 }
280
281 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
282 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, std::move(indices_ptr), opt));
283 }
284
285 /********************************
286 ******* Sparse oracular ********
287 ********************************/
288public:
289 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
290 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, opt));
291 }
292
293 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 {
294 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, block_start, block_end, opt));
295 }
296
297 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
298 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, std::move(indices_ptr), opt));
299 }
300};
301
307template<typename Value_, typename Index_, class Storage_ = std::vector<Value_> >
308class DenseColumnMatrix : public DenseMatrix<Value_, Index_, Storage_> {
309public:
316};
317
323template<typename Value_, typename Index_, class Storage_ = std::vector<Value_> >
324class DenseRowMatrix : public DenseMatrix<Value_, Index_, Storage_> {
325public:
332};
333
334}
335
336#endif
Wrapper classes for sparse extraction from a dense tatami::Matrix.
Dense column-major matrix.
Definition DenseMatrix.hpp:308
DenseColumnMatrix(Index_ nrow, Index_ ncol, Storage_ values)
Definition DenseMatrix.hpp:315
Dense matrix representation.
Definition DenseMatrix.hpp:168
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, const Options &) const
Definition DenseMatrix.hpp:228
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:293
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const
Definition DenseMatrix.hpp:256
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DenseMatrix.hpp:273
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, VectorPtr< Index_ > indices_ptr, const Options &) const
Definition DenseMatrix.hpp:244
DenseMatrix(Index_ nrow, Index_ ncol, Storage_ values, bool row_major)
Definition DenseMatrix.hpp:177
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:281
double prefer_rows_proportion() const
Definition DenseMatrix.hpp:201
bool prefer_rows() const
Definition DenseMatrix.hpp:193
bool is_sparse() const
Definition DenseMatrix.hpp:197
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:297
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DenseMatrix.hpp:264
bool uses_oracle(bool) const
Definition DenseMatrix.hpp:195
double is_sparse_proportion() const
Definition DenseMatrix.hpp:199
Index_ nrow() const
Definition DenseMatrix.hpp:189
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, Index_ block_start, Index_ block_length, const Options &) const
Definition DenseMatrix.hpp:236
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DenseMatrix.hpp:260
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:277
Index_ ncol() const
Definition DenseMatrix.hpp:191
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DenseMatrix.hpp:289
Dense row-major matrix.
Definition DenseMatrix.hpp:324
DenseRowMatrix(Index_ nrow, Index_ ncol, Storage_ values)
Definition DenseMatrix.hpp:331
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