tatami
C++ API for different matrix representations
Loading...
Searching...
No Matches
DelayedCast.hpp
Go to the documentation of this file.
1#ifndef TATAMI_DELAYED_CAST_HPP
2#define TATAMI_DELAYED_CAST_HPP
3
4#include "../base/Matrix.hpp"
6
7#include <memory>
8#include <type_traits>
9#include <algorithm>
10#include <cstddef>
11
18namespace tatami {
19
23namespace DelayedCast_internal {
24
25template<typename IndexIn_, typename IndexOut_>
26class CastOracle final : public Oracle<IndexIn_> {
27public:
28 CastOracle(std::shared_ptr<const Oracle<IndexOut_> > oracle) : my_oracle(std::move(oracle)) {}
29
30 IndexIn_ get(std::size_t i) const {
31 return my_oracle->get(i);
32 }
33
34 std::size_t total() const {
35 return my_oracle->total();
36 }
37
38private:
39 std::shared_ptr<const Oracle<IndexOut_> > my_oracle;
40};
41
42template<bool oracle_, typename IndexIn_, typename IndexOut_>
43MaybeOracle<oracle_, IndexIn_> convert(MaybeOracle<oracle_, IndexOut_> oracle) {
44 if constexpr(!oracle_) {
45 return false;
46 } else if constexpr(std::is_same<IndexIn_, IndexOut_>::value) {
47 return oracle;
48 } else {
49 return std::make_shared<CastOracle<IndexIn_, IndexOut_> >(std::move(oracle));
50 }
51}
52
53template<typename IndexIn_, typename IndexOut_>
54VectorPtr<IndexIn_> convert(VectorPtr<IndexOut_> indices_ptr) {
55 if constexpr(std::is_same<IndexIn_, IndexOut_>::value) {
56 return indices_ptr;
57 } else {
58 return std::make_shared<std::vector<IndexIn_> >(indices_ptr->begin(), indices_ptr->end());
59 }
60}
61
62template<bool oracle_, typename ValueOut_, typename IndexOut_, typename ValueIn_, typename IndexIn_>
63class Dense final : public DenseExtractor<oracle_, ValueOut_, IndexOut_> {
64public:
65 Dense(const Matrix<ValueIn_, IndexIn_>* matrix, bool row, MaybeOracle<oracle_, IndexOut_> oracle, const Options& opt) {
66 allocate(row ? matrix->ncol() : matrix->nrow());
67 my_ext = new_extractor<false, oracle_>(matrix, row, convert<oracle_, IndexIn_, IndexOut_>(std::move(oracle)), opt);
68 }
69
70 Dense(const Matrix<ValueIn_, IndexIn_>* matrix, bool row, MaybeOracle<oracle_, IndexOut_> oracle, IndexOut_ block_start, IndexOut_ block_length, const Options& opt) {
71 allocate(block_length);
72 my_ext = new_extractor<false, oracle_>(matrix, row, convert<oracle_, IndexIn_, IndexOut_>(std::move(oracle)), block_start, block_length, opt);
73 }
74
75 Dense(const Matrix<ValueIn_, IndexIn_>* matrix, bool row, MaybeOracle<oracle_, IndexOut_> oracle, VectorPtr<IndexOut_> indices_ptr, const Options& opt) {
76 allocate(indices_ptr->size());
77 my_ext = new_extractor<false, oracle_>(matrix, row, convert<oracle_, IndexIn_, IndexOut_>(std::move(oracle)), convert<IndexIn_>(std::move(indices_ptr)), opt);
78 }
79
80private:
81 void allocate(std::size_t n) {
82 if constexpr(!no_op) {
83 my_buffer.resize(n);
84 }
85 }
86
87public:
88 const ValueOut_* fetch(IndexOut_ i, ValueOut_* buffer) {
89 if constexpr(no_op) {
90 return my_ext->fetch(i, buffer);
91 } else {
92 auto ptr = my_ext->fetch(i, my_buffer.data());
93 std::copy_n(ptr, my_buffer.size(), buffer);
94 return buffer;
95 }
96 }
97
98private:
99 std::unique_ptr<DenseExtractor<oracle_, ValueIn_, IndexIn_> > my_ext;
100 static constexpr bool no_op = std::is_same<ValueOut_, ValueIn_>::value;
101 typename std::conditional<no_op, bool, std::vector<ValueIn_> >::type my_buffer;
102};
103
104template<bool oracle_, typename ValueOut_, typename IndexOut_, typename ValueIn_, typename IndexIn_>
105class Sparse final : public SparseExtractor<oracle_, ValueOut_, IndexOut_> {
106public:
107 Sparse(const Matrix<ValueIn_, IndexIn_>* matrix, bool row, MaybeOracle<oracle_, IndexOut_> oracle, const Options& opt) {
108 allocate(row ? matrix->ncol() : matrix->nrow(), opt);
109 my_ext = new_extractor<true, oracle_>(matrix, row, convert<oracle_, IndexIn_, IndexOut_>(std::move(oracle)), opt);
110 }
111
112 Sparse(const Matrix<ValueIn_, IndexIn_>* matrix, bool row, MaybeOracle<oracle_, IndexOut_> oracle, IndexOut_ block_start, IndexOut_ block_length, const Options& opt) {
113 allocate(block_length, opt);
114 my_ext = new_extractor<true, oracle_>(matrix, row, convert<oracle_, IndexIn_, IndexOut_>(std::move(oracle)), block_start, block_length, opt);
115 }
116
117 Sparse(const Matrix<ValueIn_, IndexIn_>* matrix, bool row, MaybeOracle<oracle_, IndexOut_> oracle, VectorPtr<IndexOut_> indices_ptr, const Options& opt) {
118 allocate(indices_ptr->size(), opt);
119 my_ext = new_extractor<true, oracle_>(matrix, row, convert<oracle_, IndexIn_, IndexOut_>(std::move(oracle)), convert<IndexIn_>(std::move(indices_ptr)), opt);
120 }
121
122private:
123 void allocate(std::size_t n, const Options& opt) {
124 if constexpr(!no_op_value) {
125 if (opt.sparse_extract_value) {
126 my_vbuffer.resize(n);
127 }
128 }
129 if constexpr(!no_op_index) {
130 if (opt.sparse_extract_index) {
131 my_ibuffer.resize(n);
132 }
133 }
134 }
135
136public:
137 SparseRange<ValueOut_, IndexOut_> fetch(IndexOut_ i, ValueOut_* value_buffer, IndexOut_* index_buffer) {
138 IndexIn_* iptr = [&]{
139 if constexpr(no_op_index) {
140 return index_buffer;
141 } else {
142 return my_ibuffer.data();
143 }
144 }();
145
146 ValueIn_* vptr = [&]{
147 if constexpr(no_op_value) {
148 return value_buffer;
149 } else {
150 return my_vbuffer.data();
151 }
152 }();
153
154 auto range = my_ext->fetch(i, vptr, iptr);
155 SparseRange<ValueOut_, IndexOut_> output(range.number);
156
157 if constexpr(no_op_index) {
158 output.index = range.index;
159 } else if (range.index != NULL) {
160 std::copy_n(range.index, range.number, index_buffer);
161 output.index = index_buffer;
162 }
163
164 if constexpr(no_op_value) {
165 output.value = range.value;
166 } else if (range.value != NULL) {
167 std::copy_n(range.value, range.number, value_buffer);
168 output.value = value_buffer;
169 }
170
171 return output;
172 }
173
174private:
175 std::unique_ptr<SparseExtractor<oracle_, ValueIn_, IndexIn_> > my_ext;
176 static constexpr bool no_op_value = std::is_same<ValueOut_, ValueIn_>::value;
177 typename std::conditional<no_op_value, bool, std::vector<ValueIn_> >::type my_vbuffer;
178 static constexpr bool no_op_index = std::is_same<IndexOut_, IndexIn_>::value;
179 typename std::conditional<no_op_index, bool, std::vector<IndexIn_> >::type my_ibuffer;
180};
181
182}
200template<typename ValueOut_, typename IndexOut_, typename ValueIn_, typename IndexIn_>
201class DelayedCast final : public Matrix<ValueOut_, IndexOut_> {
202public:
206 DelayedCast(std::shared_ptr<const Matrix<ValueIn_, IndexIn_> > matrix) : my_matrix(std::move(matrix)) {}
207
208public:
209 IndexOut_ nrow() const {
210 return my_matrix->nrow();
211 }
212
213 IndexOut_ ncol() const {
214 return my_matrix->ncol();
215 }
216
217 bool is_sparse() const {
218 return my_matrix->is_sparse();
219 }
220
221 double is_sparse_proportion() const {
222 return my_matrix->is_sparse_proportion();
223 }
224
225 bool prefer_rows() const {
226 return my_matrix->prefer_rows();
227 }
228
229 double prefer_rows_proportion() const {
230 return my_matrix->prefer_rows_proportion();
231 }
232
233 bool uses_oracle(bool row) const {
234 return my_matrix->uses_oracle(row);
235 }
236
237private:
238 std::shared_ptr<const Matrix<ValueIn_, IndexIn_> > my_matrix;
239
240 /********************
241 *** Myopic dense ***
242 ********************/
243public:
244 std::unique_ptr<MyopicDenseExtractor<ValueOut_, IndexOut_> > dense(bool row, const Options& opt) const {
245 return std::make_unique<DelayedCast_internal::Dense<false, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, false, opt);
246 }
247
248 std::unique_ptr<MyopicDenseExtractor<ValueOut_, IndexOut_> > dense(bool row, IndexOut_ block_start, IndexOut_ block_length, const Options& opt) const {
249 return std::make_unique<DelayedCast_internal::Dense<false, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, false, block_start, block_length, opt);
250 }
251
252 std::unique_ptr<MyopicDenseExtractor<ValueOut_, IndexOut_> > dense(bool row, VectorPtr<IndexOut_> indices_my_matrix, const Options& opt) const {
253 return std::make_unique<DelayedCast_internal::Dense<false, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, false, std::move(indices_my_matrix), opt);
254 }
255
256 /*********************
257 *** Myopic sparse ***
258 *********************/
259public:
260 std::unique_ptr<MyopicSparseExtractor<ValueOut_, IndexOut_> > sparse(bool row, const Options& opt) const {
261 return std::make_unique<DelayedCast_internal::Sparse<false, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, false, opt);
262 }
263
264 std::unique_ptr<MyopicSparseExtractor<ValueOut_, IndexOut_> > sparse(bool row, IndexOut_ block_start, IndexOut_ block_length, const Options& opt) const {
265 return std::make_unique<DelayedCast_internal::Sparse<false, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, false, block_start, block_length, opt);
266 }
267
268 std::unique_ptr<MyopicSparseExtractor<ValueOut_, IndexOut_> > sparse(bool row, VectorPtr<IndexOut_> indices_my_matrix, const Options& opt) const {
269 return std::make_unique<DelayedCast_internal::Sparse<false, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, false, std::move(indices_my_matrix), opt);
270 }
271
272 /**********************
273 *** Oracular dense ***
274 **********************/
275public:
276 std::unique_ptr<OracularDenseExtractor<ValueOut_, IndexOut_> > dense(bool row, std::shared_ptr<const Oracle<IndexOut_> > oracle, const Options& opt) const {
277 return std::make_unique<DelayedCast_internal::Dense<true, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, std::move(oracle), opt);
278 }
279
280 std::unique_ptr<OracularDenseExtractor<ValueOut_, IndexOut_> > dense(bool row, std::shared_ptr<const Oracle<IndexOut_> > oracle, IndexOut_ block_start, IndexOut_ block_length, const Options& opt) const {
281 return std::make_unique<DelayedCast_internal::Dense<true, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, std::move(oracle), block_start, block_length, opt);
282 }
283
284 std::unique_ptr<OracularDenseExtractor<ValueOut_, IndexOut_> > dense(bool row, std::shared_ptr<const Oracle<IndexOut_> > oracle, VectorPtr<IndexOut_> indices_my_matrix, const Options& opt) const {
285 return std::make_unique<DelayedCast_internal::Dense<true, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, std::move(oracle), std::move(indices_my_matrix), opt);
286 }
287
288 /***********************
289 *** Oracular sparse ***
290 ***********************/
291public:
292 std::unique_ptr<OracularSparseExtractor<ValueOut_, IndexOut_> > sparse(bool row, std::shared_ptr<const Oracle<IndexOut_> > oracle, const Options& opt) const {
293 return std::make_unique<DelayedCast_internal::Sparse<true, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, std::move(oracle), opt);
294 }
295
296 std::unique_ptr<OracularSparseExtractor<ValueOut_, IndexOut_> > sparse(bool row, std::shared_ptr<const Oracle<IndexOut_> > oracle, IndexOut_ block_start, IndexOut_ block_length, const Options& opt) const {
297 return std::make_unique<DelayedCast_internal::Sparse<true, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, std::move(oracle), block_start, block_length, opt);
298 }
299
300 std::unique_ptr<OracularSparseExtractor<ValueOut_, IndexOut_> > sparse(bool row, std::shared_ptr<const Oracle<IndexOut_> > oracle, VectorPtr<IndexOut_> indices_my_matrix, const Options& opt) const {
301 return std::make_unique<DelayedCast_internal::Sparse<true, ValueOut_, IndexOut_, ValueIn_, IndexIn_> >(my_matrix.get(), row, std::move(oracle), std::move(indices_my_matrix), opt);
302 }
303};
304
316template<typename ValueOut_, typename IndexOut_, typename ValueIn_, typename IndexIn_>
317std::shared_ptr<Matrix<ValueOut_, IndexOut_> > make_DelayedCast(std::shared_ptr<const Matrix<ValueIn_, IndexIn_> > p) {
318 return std::shared_ptr<Matrix<ValueOut_, IndexOut_> >(new DelayedCast<ValueOut_, IndexOut_, ValueIn_, IndexIn_>(std::move(p)));
319}
320
324template<typename ValueOut_, typename IndexOut_, typename ValueIn_, typename IndexIn_>
325std::shared_ptr<Matrix<ValueOut_, IndexOut_> > make_DelayedCast(std::shared_ptr<Matrix<ValueIn_, IndexIn_> > p) {
326 return std::shared_ptr<Matrix<ValueOut_, IndexOut_> >(new DelayedCast<ValueOut_, IndexOut_, ValueIn_, IndexIn_>(std::move(p)));
327}
332}
333
334#endif
Virtual class for a matrix of some numeric type.
Recast a Matrix to a different interface type.
Definition DelayedCast.hpp:201
std::unique_ptr< OracularDenseExtractor< ValueOut_, IndexOut_ > > dense(bool row, std::shared_ptr< const Oracle< IndexOut_ > > oracle, IndexOut_ block_start, IndexOut_ block_length, const Options &opt) const
Definition DelayedCast.hpp:280
std::unique_ptr< MyopicDenseExtractor< ValueOut_, IndexOut_ > > dense(bool row, IndexOut_ block_start, IndexOut_ block_length, const Options &opt) const
Definition DelayedCast.hpp:248
std::unique_ptr< OracularDenseExtractor< ValueOut_, IndexOut_ > > dense(bool row, std::shared_ptr< const Oracle< IndexOut_ > > oracle, VectorPtr< IndexOut_ > indices_my_matrix, const Options &opt) const
Definition DelayedCast.hpp:284
std::unique_ptr< MyopicSparseExtractor< ValueOut_, IndexOut_ > > sparse(bool row, const Options &opt) const
Definition DelayedCast.hpp:260
DelayedCast(std::shared_ptr< const Matrix< ValueIn_, IndexIn_ > > matrix)
Definition DelayedCast.hpp:206
std::unique_ptr< MyopicDenseExtractor< ValueOut_, IndexOut_ > > dense(bool row, VectorPtr< IndexOut_ > indices_my_matrix, const Options &opt) const
Definition DelayedCast.hpp:252
std::unique_ptr< OracularDenseExtractor< ValueOut_, IndexOut_ > > dense(bool row, std::shared_ptr< const Oracle< IndexOut_ > > oracle, const Options &opt) const
Definition DelayedCast.hpp:276
double prefer_rows_proportion() const
Definition DelayedCast.hpp:229
IndexOut_ nrow() const
Definition DelayedCast.hpp:209
std::unique_ptr< OracularSparseExtractor< ValueOut_, IndexOut_ > > sparse(bool row, std::shared_ptr< const Oracle< IndexOut_ > > oracle, IndexOut_ block_start, IndexOut_ block_length, const Options &opt) const
Definition DelayedCast.hpp:296
std::unique_ptr< MyopicSparseExtractor< ValueOut_, IndexOut_ > > sparse(bool row, IndexOut_ block_start, IndexOut_ block_length, const Options &opt) const
Definition DelayedCast.hpp:264
std::unique_ptr< OracularSparseExtractor< ValueOut_, IndexOut_ > > sparse(bool row, std::shared_ptr< const Oracle< IndexOut_ > > oracle, VectorPtr< IndexOut_ > indices_my_matrix, const Options &opt) const
Definition DelayedCast.hpp:300
bool is_sparse() const
Definition DelayedCast.hpp:217
bool uses_oracle(bool row) const
Definition DelayedCast.hpp:233
IndexOut_ ncol() const
Definition DelayedCast.hpp:213
double is_sparse_proportion() const
Definition DelayedCast.hpp:221
std::unique_ptr< MyopicDenseExtractor< ValueOut_, IndexOut_ > > dense(bool row, const Options &opt) const
Definition DelayedCast.hpp:244
bool prefer_rows() const
Definition DelayedCast.hpp:225
std::unique_ptr< OracularSparseExtractor< ValueOut_, IndexOut_ > > sparse(bool row, std::shared_ptr< const Oracle< IndexOut_ > > oracle, const Options &opt) const
Definition DelayedCast.hpp:292
std::unique_ptr< MyopicSparseExtractor< ValueOut_, IndexOut_ > > sparse(bool row, VectorPtr< IndexOut_ > indices_my_matrix, const Options &opt) const
Definition DelayedCast.hpp:268
Virtual class for a matrix.
Definition Matrix.hpp:59
Predict future access requests on the target dimension.
Definition Oracle.hpp:23
Flexible representations for matrix data.
Definition Extractor.hpp:15
std::shared_ptr< const std::vector< Index_ > > VectorPtr
Definition Matrix.hpp:26
typename std::conditional< oracle_, OracularDenseExtractor< Value_, Index_ >, MyopicDenseExtractor< Value_, Index_ > >::type DenseExtractor
Definition Extractor.hpp:273
std::shared_ptr< Matrix< ValueOut_, IndexOut_ > > make_DelayedCast(std::shared_ptr< const Matrix< ValueIn_, IndexIn_ > > p)
Definition DelayedCast.hpp:317
Templated construction of a new extractor.
Options for accessing data from a Matrix instance.
Definition Options.hpp:30