1#ifndef TATAMI_CONVERT_TO_FRAGMENTED_SPARSE_H
2#define TATAMI_CONVERT_TO_FRAGMENTED_SPARSE_H
11#include "convert_to_sparse_utils.hpp"
36template<
typename Value_,
typename Index_>
53 std::vector<std::vector<Value_> >
value;
60 std::vector<std::vector<Index_> >
index;
83template<
typename StoredValue_,
typename StoredIndex_,
typename InputValue_,
typename InputIndex_>
89 const InputIndex_ NR = matrix.
nrow();
90 const InputIndex_ NC = matrix.
ncol();
91 const InputIndex_ primary = (row ? NR : NC);
92 const InputIndex_ secondary = (row ? NC : NR);
95 auto& store_v = output.
value;
96 auto& store_i = output.
index;
99 parallelize([&](
const int,
const InputIndex_ start,
const InputIndex_ length) ->
void {
104 for (InputIndex_ p = start, pe = start + length; p < pe; ++p) {
105 const auto range = wrk->fetch(buffer_v.data(), buffer_i.data());
106 auto& sv = store_v[p];
107 auto& si = store_i[p];
108 sv.reserve(range.number);
109 si.reserve(range.number);
112 for (InputIndex_ i = 0; i < range.number; ++i) {
113 sv.push_back(range.value[i]);
114 si.push_back(range.index[i]);
120 parallelize([&](
const int,
const InputIndex_ start,
const InputIndex_ length) ->
void {
124 for (InputIndex_ p = start, pe = start + length; p < pe; ++p) {
125 const auto ptr = wrk->fetch(buffer_v.data());
126 auto& sv = store_v[p];
127 auto& si = store_i[p];
130 for (InputIndex_ s = 0; s < secondary; ++s) {
131 const auto val = ptr[s];
145template<
typename StoredValue_,
typename StoredIndex_,
typename InputValue_,
typename InputIndex_>
146FragmentedSparseContents<StoredValue_, StoredIndex_> retrieve_fragmented_sparse_inconsistent_one_pass(
149 const int num_threads
151 const InputIndex_ NR = matrix.
nrow();
152 const InputIndex_ NC = matrix.
ncol();
153 const InputIndex_ primary = (row ? NR : NC);
154 const InputIndex_ secondary = (row ? NC : NR);
158 std::vector<std::vector<InputValue_> > store_v;
159 std::vector<std::vector<InputIndex_> > store_i;
160 auto original_ranges = extract_sparse_matrix(matrix, store_v, store_i, num_threads);
163 for (I<
decltype(secondary)> s = 0; s < secondary; ++s) {
164 const auto& sec_indices = original_ranges[s].index;
165 const auto num = original_ranges[s].number;
166 for (I<
decltype(num)> n = 0; n < num; ++n) {
167 primary_counts[sec_indices[n]] += 1;
171 FragmentedSparseContents<StoredValue_, StoredIndex_> output(primary);
172 for (InputIndex_ p = 0; p < primary; ++p) {
173 output.
index[p].reserve(primary_counts[p]);
174 output.
value[p].reserve(primary_counts[p]);
177 for (I<
decltype(secondary)> s = 0; s < secondary; ++s) {
178 const auto& sec_values = original_ranges[s].value;
179 const auto& sec_indices = original_ranges[s].index;
180 const auto num = original_ranges[s].number;
181 for (I<
decltype(num)> n = 0; n < num; ++n) {
182 const auto curp = sec_indices[n];
183 output.
value[curp].push_back(sec_values[n]);
184 output.
index[curp].push_back(s);
191template<
typename StoredValue_,
typename StoredIndex_,
typename InputValue_,
typename InputIndex_>
192FragmentedSparseContents<StoredValue_, StoredIndex_> retrieve_fragmented_sparse_inconsistent_two_pass(
195 const int num_threads
197 const InputIndex_ NR = matrix.
nrow();
198 const InputIndex_ NC = matrix.
ncol();
199 const InputIndex_ primary = (row ? NR : NC);
200 const InputIndex_ secondary = (row ? NC : NR);
204 auto per_thread = count_sparse_non_zeros_inconsistent(matrix, primary, secondary, row, nnz_inconsistent.data(), num_threads);
206 FragmentedSparseContents<StoredValue_, StoredIndex_> output(primary);
209 for (InputIndex_ p = 0; p < primary; ++p) {
210 assert(nnz_inconsistent[p] <= secondary);
211 output.
index[p].resize(nnz_inconsistent[p]);
212 output.
value[p].resize(nnz_inconsistent[p]);
215 const bool is_sparse = matrix.
is_sparse();
216 if (per_thread.has_value()) {
218 auto& offsets = per_thread->counts;
219 for (InputIndex_ i = 0; i < primary; ++i) {
220 InputIndex_ accumulant = 0;
221 static_assert(std::is_same<I<
decltype(per_thread->counts[0][0])>, InputIndex_>::value);
222 for (
auto& pt : offsets) {
223 const auto count = pt[i];
229 parallelize([&](
const int,
const int th_start,
const int th_length) ->
void {
230 for (
int t = 0; t < th_length; ++t) {
231 auto& offsets = (per_thread->counts)[t + th_start];
232 const auto actual_start = (per_thread->starts)[t + th_start];
233 const auto actual_length = (per_thread->lengths)[t + th_start];
238 opt.sparse_ordered_index =
false;
242 for (InputIndex_ x = 0; x < actual_length; ++x) {
243 const auto range = wrk->fetch(buffer_v.data(), buffer_i.data());
244 for (InputIndex_ i = 0; i < range.number; ++i) {
245 const auto prim = range.index[i];
246 auto& pos = offsets[prim];
247 output.
value[prim][pos] = range.value[i];
248 output.
index[prim][pos] = x + actual_start;
256 for (InputIndex_ x = 0; x < actual_length; ++x) {
257 const auto ptr = wrk->fetch(buffer_v.data());
258 for (InputIndex_ p = 0; p < primary; ++p) {
259 const auto val = ptr[p];
261 auto& pos = offsets[p];
262 output.
value[p][pos] = val;
263 output.
index[p][pos] = x + actual_start;
270 }, per_thread->counts.size(), per_thread->counts.size());
277 opt.sparse_ordered_index =
false;
281 for (InputIndex_ s = 0; s < secondary; ++s) {
282 const auto range = wrk->fetch(buffer_v.data(), buffer_i.data());
283 for (InputIndex_ i = 0; i < range.number; ++i) {
284 const auto prim = range.index[i];
285 auto& pos = offsets[prim];
286 output.
value[prim][pos] = range.value[i];
287 output.
index[prim][pos] = s;
295 for (InputIndex_ s = 0; s < secondary; ++s) {
296 const auto ptr = wrk->fetch(buffer_v.data());
297 for (InputIndex_ p = 0; p < primary; ++p) {
298 const auto val = ptr[p];
300 auto& pos = offsets[p];
301 output.
value[p][pos] = val;
302 output.
index[p][pos] = s;
328template<
typename StoredValue_,
typename StoredIndex_,
typename InputValue_,
typename InputIndex_>
335 return retrieve_fragmented_sparse_contents_consistent<StoredValue_, StoredIndex_>(matrix, row, options);
339 return retrieve_fragmented_sparse_inconsistent_one_pass<StoredValue_, StoredIndex_>(matrix, row, options.
num_threads);
342 return retrieve_fragmented_sparse_inconsistent_two_pass<StoredValue_, StoredIndex_>(matrix, row, options.
num_threads);
380 typename StoredValue_ = Value_,
381 typename StoredIndex_ = Index_,
382 typename InputValue_,
400 return std::shared_ptr<Matrix<Value_, Index_> >(
404 std::vector<std::vector<StoredValue_> >,
405 std::vector<std::vector<StoredIndex_> >
409 std::move(frag.value),
410 std::move(frag.index),
413 FragmentedSparseMatrixOptions fopt;
425template<
typename Value_,
typename Index_,
typename StoredValue_ = Value_,
typename StoredIndex_ = Index_,
typename InputValue_,
typename InputIndex_>
426std::shared_ptr<Matrix<Value_, Index_> >
convert_to_fragmented_sparse(
const Matrix<InputValue_, InputIndex_>* matrix,
bool row,
int threads = 1) {
431 ConvertToFragmentedSparseOptions opt;
432 opt.num_threads = threads;
438template<
typename StoredValue_,
typename StoredIndex_,
typename InputValue_,
typename InputIndex_>
444 RetrieveFragmentedSparseContentsOptions opt;
445 opt.num_threads = threads;
451template <
bool row_,
typename StoredValue_,
typename StoredIndex_,
typename InputValue_,
typename InputIndex_>
456template <
bool row_,
typename Value_,
typename Index_,
typename StoredValue_ = Value_,
typename StoredIndex_ = Index_,
typename InputValue_,
typename InputIndex_>
Fragmented sparse matrix representation.
Convert index type to container size.
Fragmented sparse matrix representation.
Definition FragmentedSparseMatrix.hpp:570
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
Copy data from one buffer to another.
Flexible representations for matrix data.
Definition Extractor.hpp:15
FragmentedSparseContents< StoredValue_, StoredIndex_ > retrieve_fragmented_sparse_contents(const Matrix< InputValue_, InputIndex_ > &matrix, const bool row, const RetrieveFragmentedSparseContentsOptions &options)
Definition convert_to_fragmented_sparse.hpp:329
int parallelize(Function_ fun, const Index_ tasks, const int workers)
Definition parallelize.hpp:58
I< decltype(std::declval< Container_ >().size())> cast_Index_to_container_size(const Index_ x)
Definition Index_to_container.hpp:65
std::shared_ptr< Matrix< Value_, Index_ > > convert_to_fragmented_sparse(const Matrix< InputValue_, InputIndex_ > &matrix, const bool row, const ConvertToFragmentedSparseOptions &options)
Definition convert_to_fragmented_sparse.hpp:385
Container_ create_container_of_Index_size(const Index_ x, Args_ &&... args)
Definition Index_to_container.hpp:82
auto consecutive_extractor(const Matrix< Value_, Index_ > &matrix, const bool row, const Index_ iter_start, const 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:348
bool two_pass
Definition convert_to_fragmented_sparse.hpp:354
int num_threads
Definition convert_to_fragmented_sparse.hpp:359
Fragmented sparse contents.
Definition convert_to_fragmented_sparse.hpp:37
std::vector< std::vector< Value_ > > value
Definition convert_to_fragmented_sparse.hpp:53
std::vector< std::vector< Index_ > > index
Definition convert_to_fragmented_sparse.hpp:60
Options for retrieve_fragmented_sparse_contents().
Definition convert_to_fragmented_sparse.hpp:66
int num_threads
Definition convert_to_fragmented_sparse.hpp:77
bool two_pass
Definition convert_to_fragmented_sparse.hpp:72