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
5#include "../utils/parallelize.hpp"
6#include "../utils/consecutive_extractor.hpp"
7
8#include <memory>
9#include <vector>
10
17namespace tatami {
18
29template<typename Value_, typename Index_>
34 FragmentedSparseContents(size_t n) : value(n), index(n) {}
43 std::vector<std::vector<Value_> > value;
44
50 std::vector<std::vector<Index_> > index;
51};
52
65template<typename StoredValue_, typename StoredIndex_, typename InputValue_, typename InputIndex_>
67 InputIndex_ NR = matrix->nrow();
68 InputIndex_ NC = matrix->ncol();
69 InputIndex_ primary = (row ? NR : NC);
70 InputIndex_ secondary = (row ? NC : NR);
71
73 auto& store_v = output.value;
74 auto& store_i = output.index;
75
76 if (row == matrix->prefer_rows()) {
77 if (matrix->is_sparse()) {
79 std::vector<InputValue_> buffer_v(secondary);
80 std::vector<InputIndex_> buffer_i(secondary);
82
83 for (InputIndex_ p = start, pe = start + length; p < pe; ++p) {
84 auto range = wrk->fetch(buffer_v.data(), buffer_i.data());
85 auto& sv = store_v[p];
86 auto& si = store_i[p];
87 sv.reserve(range.number);
88 si.reserve(range.number);
89
90 for (InputIndex_ i = 0; i < range.number; ++i, ++range.value, ++range.index) {
91 if (*range.value) {
92 sv.push_back(*range.value);
93 si.push_back(*range.index);
94 }
95 }
96 }
97 }, primary, threads);
98
99 } else {
100 parallelize([&](int, InputIndex_ start, InputIndex_ length) -> void {
101 std::vector<InputValue_> buffer_v(secondary);
103
104 // Special conversion from dense to save ourselves from having to make
105 // indices that we aren't really interested in.
106 for (InputIndex_ p = start, pe = start + length; p < pe; ++p) {
107 auto ptr = wrk->fetch(buffer_v.data());
108 auto& sv = store_v[p];
109 auto& si = store_i[p];
110
111 for (InputIndex_ s = 0; s < secondary; ++s, ++ptr) {
112 if (*ptr) {
113 sv.push_back(*ptr);
114 si.push_back(s);
115 }
116 }
117 }
118 }, primary, threads);
119 }
120
121 } else {
122 // We iterate on the matrix matrix's preferred dimension, under the
123 // assumption that it may be arbitrarily costly to extract in the
124 // non-preferred dim; it is thus cheaper to do cache-unfriendly inserts
125 // into the output buffers.
126
127 if (matrix->is_sparse()) {
128 parallelize([&](int, InputIndex_ start, InputIndex_ length) -> void {
129 std::vector<InputValue_> buffer_v(primary);
130 std::vector<InputIndex_> buffer_i(primary);
131 auto wrk = consecutive_extractor<true>(matrix, !row, static_cast<InputIndex_>(0), secondary, start, length);
132
133 for (InputIndex_ x = 0; x < secondary; ++x) {
134 auto range = wrk->fetch(buffer_v.data(), buffer_i.data());
135 for (InputIndex_ i = 0; i < range.number; ++i, ++range.value, ++range.index) {
136 if (*range.value) {
137 store_v[*range.index].push_back(*range.value);
138 store_i[*range.index].push_back(x);
139 }
140 }
141 }
142 }, primary, threads);
143
144 } else {
145 parallelize([&](int, InputIndex_ start, InputIndex_ length) -> void {
146 auto wrk = consecutive_extractor<false>(matrix, !row, static_cast<InputIndex_>(0), secondary, start, length);
147 std::vector<InputValue_> buffer_v(length);
148
149 for (InputIndex_ x = 0; x < secondary; ++x) {
150 auto ptr = wrk->fetch(buffer_v.data());
151 for (InputIndex_ p = start, pe = start + length; p < pe; ++p, ++ptr) {
152 if (*ptr) {
153 store_v[p].push_back(*ptr);
154 store_i[p].push_back(x);
155 }
156 }
157 }
158 }, primary, threads);
159 }
160 }
161
162 return output;
163}
164
180template<typename Value_, typename Index_, typename StoredValue_ = Value_, typename StoredIndex_ = Index_, typename InputValue_, typename InputIndex_>
181std::shared_ptr<Matrix<Value_, Index_> > convert_to_fragmented_sparse(const Matrix<InputValue_, InputIndex_>* matrix, bool row, int threads = 1) {
183 return std::shared_ptr<Matrix<Value_, Index_> >(
185 Value_,
186 Index_,
187 std::vector<std::vector<StoredValue_> >,
188 std::vector<std::vector<StoredIndex_> >
189 >(
190 matrix->nrow(),
191 matrix->ncol(),
192 std::move(frag.value),
193 std::move(frag.index),
194 row,
195 false // no need for checks, as we guarantee correctness.
196 )
197 );
198}
199
203// Backwards compatbility.
204template <bool row_, typename StoredValue_, typename StoredIndex_, typename InputValue_, typename InputIndex_>
207}
208
209template <bool row_, typename Value_, typename Index_, typename StoredValue_ = Value_, typename StoredIndex_ = Index_, typename InputValue_, typename InputIndex_>
210std::shared_ptr<Matrix<Value_, Index_> > convert_to_fragmented_sparse(const Matrix<InputValue_, InputIndex_>* matrix, int threads = 1) {
212}
217}
218
219#endif
Fragmented sparse matrix representation.
Fragmented sparse matrix representation.
Definition FragmentedSparseMatrix.hpp:435
Virtual class for a matrix.
Definition Matrix.hpp:59
Flexible representations for matrix data.
Definition Extractor.hpp:15
std::shared_ptr< Matrix< Value_, Index_ > > convert_to_fragmented_sparse(const Matrix< InputValue_, InputIndex_ > *matrix, bool row, int threads=1)
Definition convert_to_fragmented_sparse.hpp:181
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, int threads=1)
Definition convert_to_fragmented_sparse.hpp:66
auto consecutive_extractor(const Matrix< Value_, Index_ > *mat, bool row, Index_ iter_start, Index_ iter_length, Args_ &&... args)
Definition consecutive_extractor.hpp:35
Fragmented sparse contents.
Definition convert_to_fragmented_sparse.hpp:30
std::vector< std::vector< Value_ > > value
Definition convert_to_fragmented_sparse.hpp:43
std::vector< std::vector< Index_ > > index
Definition convert_to_fragmented_sparse.hpp:50