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