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