tatami
C++ API for different matrix representations
Loading...
Searching...
No Matches
convert_to_fragmented_sparse.hpp
Go to the documentation of this file.
1#ifndef TATAMI_CONVERT_TO_FRAGMENTED_SPARSE_H
2#define TATAMI_CONVERT_TO_FRAGMENTED_SPARSE_H
3
7
8#include <memory>
9#include <vector>
10#include <cstddef>
11
18namespace tatami {
19
30template<typename Value_, typename Index_>
35 FragmentedSparseContents(std::size_t n) : value(n), index(n) {}
44 std::vector<std::vector<Value_> > value;
45
51 std::vector<std::vector<Index_> > index;
52};
53
63
76template<typename StoredValue_, typename StoredIndex_, typename InputValue_, typename InputIndex_>
79 bool row,
81{
82 InputIndex_ NR = matrix.nrow();
83 InputIndex_ NC = matrix.ncol();
84 InputIndex_ primary = (row ? NR : NC);
85 InputIndex_ secondary = (row ? NC : NR);
86
88 auto& store_v = output.value;
89 auto& store_i = output.index;
90
91 if (row == matrix.prefer_rows()) {
92 if (matrix.is_sparse()) {
93 parallelize([&](int, InputIndex_ start, InputIndex_ length) -> void {
94 std::vector<InputValue_> buffer_v(secondary);
95 std::vector<InputIndex_> buffer_i(secondary);
96 auto wrk = consecutive_extractor<true>(matrix, row, start, length);
97
98 for (InputIndex_ p = start, pe = start + length; p < pe; ++p) {
99 auto range = wrk->fetch(buffer_v.data(), buffer_i.data());
100 auto& sv = store_v[p];
101 auto& si = store_i[p];
102 sv.reserve(range.number);
103 si.reserve(range.number);
104
105 for (InputIndex_ i = 0; i < range.number; ++i, ++range.value, ++range.index) {
106 if (*range.value) {
107 sv.push_back(*range.value);
108 si.push_back(*range.index);
109 }
110 }
111 }
112 }, primary, options.num_threads);
113
114 } else {
115 parallelize([&](int, InputIndex_ start, InputIndex_ length) -> void {
116 std::vector<InputValue_> buffer_v(secondary);
117 auto wrk = consecutive_extractor<false>(matrix, row, start, length);
118
119 // Special conversion from dense to save ourselves from having to make
120 // indices that we aren't really interested in.
121 for (InputIndex_ p = start, pe = start + length; p < pe; ++p) {
122 auto ptr = wrk->fetch(buffer_v.data());
123 auto& sv = store_v[p];
124 auto& si = store_i[p];
125
126 for (InputIndex_ s = 0; s < secondary; ++s, ++ptr) {
127 if (*ptr) {
128 sv.push_back(*ptr);
129 si.push_back(s);
130 }
131 }
132 }
133 }, primary, options.num_threads);
134 }
135
136 } else {
137 // We iterate on the matrix matrix's preferred dimension, under the
138 // assumption that it may be arbitrarily costly to extract in the
139 // non-preferred dim; it is thus cheaper to do cache-unfriendly inserts
140 // into the output buffers.
141
142 if (matrix.is_sparse()) {
143 parallelize([&](int, InputIndex_ start, InputIndex_ length) -> void {
144 std::vector<InputValue_> buffer_v(primary);
145 std::vector<InputIndex_> buffer_i(primary);
146 auto wrk = consecutive_extractor<true>(matrix, !row, static_cast<InputIndex_>(0), secondary, start, length);
147
148 for (InputIndex_ x = 0; x < secondary; ++x) {
149 auto range = wrk->fetch(buffer_v.data(), buffer_i.data());
150 for (InputIndex_ i = 0; i < range.number; ++i, ++range.value, ++range.index) {
151 if (*range.value) {
152 store_v[*range.index].push_back(*range.value);
153 store_i[*range.index].push_back(x);
154 }
155 }
156 }
157 }, primary, options.num_threads);
158
159 } else {
160 parallelize([&](int, InputIndex_ start, InputIndex_ length) -> void {
161 auto wrk = consecutive_extractor<false>(matrix, !row, static_cast<InputIndex_>(0), secondary, start, length);
162 std::vector<InputValue_> buffer_v(length);
163
164 for (InputIndex_ x = 0; x < secondary; ++x) {
165 auto ptr = wrk->fetch(buffer_v.data());
166 for (InputIndex_ p = start, pe = start + length; p < pe; ++p, ++ptr) {
167 if (*ptr) {
168 store_v[p].push_back(*ptr);
169 store_i[p].push_back(x);
170 }
171 }
172 }
173 }, primary, options.num_threads);
174 }
175 }
176
177 return output;
178}
179
189
205template<
206 typename Value_,
207 typename Index_,
208 typename StoredValue_ = Value_,
209 typename StoredIndex_ = Index_,
210 typename InputValue_,
211 typename InputIndex_
212>
213std::shared_ptr<Matrix<Value_, Index_> > convert_to_fragmented_sparse(
215 bool row,
217{
219 matrix,
220 row,
221 [&]{
223 ropt.num_threads = options.num_threads;
224 return ropt;
225 }()
226 );
227 return std::shared_ptr<Matrix<Value_, Index_> >(
229 Value_,
230 Index_,
231 std::vector<std::vector<StoredValue_> >,
232 std::vector<std::vector<StoredIndex_> >
233 >(
234 matrix.nrow(),
235 matrix.ncol(),
236 std::move(frag.value),
237 std::move(frag.index),
238 row,
239 []{
240 FragmentedSparseMatrixOptions fopt;
241 fopt.check = false; // no need for checks, as we guarantee correctness.
242 return fopt;
243 }()
244 )
245 );
246}
247
251// Backwards compatbility.
252template<typename Value_, typename Index_, typename StoredValue_ = Value_, typename StoredIndex_ = Index_, typename InputValue_, typename InputIndex_>
253std::shared_ptr<Matrix<Value_, Index_> > convert_to_fragmented_sparse(const Matrix<InputValue_, InputIndex_>* matrix, bool row, int threads = 1) {
255 *matrix,
256 row,
257 [&]{
258 ConvertToFragmentedSparseOptions opt;
259 opt.num_threads = threads;
260 return opt;
261 }()
262 );
263}
264
265template<typename StoredValue_, typename StoredIndex_, typename InputValue_, typename InputIndex_>
266FragmentedSparseContents<StoredValue_, StoredIndex_> retrieve_fragmented_sparse_contents(const Matrix<InputValue_, InputIndex_>* matrix, bool row, int threads = 1) {
268 *matrix,
269 row,
270 [&]{
271 RetrieveFragmentedSparseContentsOptions opt;
272 opt.num_threads = threads;
273 return opt;
274 }()
275 );
276}
277
278template <bool row_, typename StoredValue_, typename StoredIndex_, typename InputValue_, typename InputIndex_>
279FragmentedSparseContents<StoredValue_, StoredIndex_> retrieve_fragmented_sparse_contents(const Matrix<InputValue_, InputIndex_>* matrix, int threads = 1) {
281}
282
283template <bool row_, typename Value_, typename Index_, typename StoredValue_ = Value_, typename StoredIndex_ = Index_, typename InputValue_, typename InputIndex_>
284std::shared_ptr<Matrix<Value_, Index_> > convert_to_fragmented_sparse(const Matrix<InputValue_, InputIndex_>* matrix, int threads = 1) {
286}
291}
292
293#endif
Fragmented sparse matrix representation.
Fragmented sparse matrix representation.
Definition FragmentedSparseMatrix.hpp:464
Virtual class for a matrix.
Definition Matrix.hpp:59
virtual Index_ ncol() const =0
virtual Index_ nrow() const =0
virtual bool prefer_rows() const =0
virtual bool is_sparse() const =0
Templated construction of a new consecutive extractor.
Flexible representations for matrix data.
Definition Extractor.hpp:15
void parallelize(Function_ fun, Index_ tasks, int threads)
Definition parallelize.hpp:42
FragmentedSparseContents< StoredValue_, StoredIndex_ > retrieve_fragmented_sparse_contents(const Matrix< InputValue_, InputIndex_ > &matrix, bool row, const RetrieveFragmentedSparseContentsOptions &options)
Definition convert_to_fragmented_sparse.hpp:77
std::shared_ptr< Matrix< Value_, Index_ > > convert_to_fragmented_sparse(const Matrix< InputValue_, InputIndex_ > &matrix, bool row, const ConvertToFragmentedSparseOptions &options)
Definition convert_to_fragmented_sparse.hpp:213
auto consecutive_extractor(const Matrix< Value_, Index_ > &matrix, bool row, Index_ iter_start, Index_ iter_length, Args_ &&... args)
Definition consecutive_extractor.hpp:35
Parallelized iteration over a tatami::Matrix.
Options for convert_to_fragmented_sparse().
Definition convert_to_fragmented_sparse.hpp:183
int num_threads
Definition convert_to_fragmented_sparse.hpp:187
Fragmented sparse contents.
Definition convert_to_fragmented_sparse.hpp:31
std::vector< std::vector< Value_ > > value
Definition convert_to_fragmented_sparse.hpp:44
std::vector< std::vector< Index_ > > index
Definition convert_to_fragmented_sparse.hpp:51
Options for retrieve_fragmented_sparse_contents().
Definition convert_to_fragmented_sparse.hpp:57
int num_threads
Definition convert_to_fragmented_sparse.hpp:61