1#ifndef TATAMI_CONVERT_TO_COMPRESSED_SPARSE_H
2#define TATAMI_CONVERT_TO_COMPRESSED_SPARSE_H
11#include "convert_to_sparse_utils.hpp"
29template<
typename Value_,
typename Index_,
typename Count_>
30void count_compressed_sparse_non_zeros_consistent(
33 const Index_ secondary,
38 sanisizer::cast<Count_>(secondary);
42 opt.sparse_extract_value =
false;
43 opt.sparse_extract_index =
false;
44 opt.sparse_ordered_index =
false;
46 parallelize([&](
const int,
const Index_ start,
const Index_ length) ->
void {
48 for (Index_ x = 0; x < length; ++x) {
49 const auto range = wrk->fetch(NULL, NULL);
50 output[start + x] = range.number;
55 parallelize([&](
const int,
const Index_ start,
const Index_ length) ->
void {
58 for (Index_ p = start, pe = start + length; p < pe; ++p) {
59 const auto ptr = wrk->fetch(buffer_v.data());
61 for (Index_ s = 0; s < secondary; ++s) {
62 count += (ptr[s] != 0);
73struct CountCompressedSparseNonZerosOptions {
78template<
typename Value_,
typename Index_,
typename Count_>
79void count_compressed_sparse_non_zeros(
83 const CountCompressedSparseNonZerosOptions& options
85 const Index_ NR = matrix.
nrow();
86 const Index_ NC = matrix.
ncol();
87 const Index_ primary = (row ? NR : NC);
88 const Index_ secondary = (row ? NC : NR);
91 count_compressed_sparse_non_zeros_consistent(matrix, primary, secondary, row, output, options.num_threads);
93 std::fill_n(output, primary, 0);
94 std::optional<std::vector<Index_> > nnz_consistent;
95 count_sparse_non_zeros_inconsistent(matrix, primary, secondary, row, output, nnz_consistent, options.num_threads);
99template<
typename InputValue_,
typename InputIndex_,
typename Po
inter_,
typename StoredValue_,
typename StoredIndex_>
100void fill_compressed_sparse_matrix_consistent(
102 const InputIndex_ primary,
103 const InputIndex_ secondary,
105 const Pointer_*
const pointers,
106 StoredValue_*
const output_value,
107 StoredIndex_*
const output_index,
112 opt.sparse_ordered_index =
false;
114 parallelize([&](
const int,
const InputIndex_ start,
const InputIndex_ length) ->
void {
119 for (InputIndex_ p = start, pe = start + length; p < pe; ++p) {
125 const auto range = wrk->fetch(buffer_v.data(), buffer_i.data());
126 const auto offset = pointers[p];
127 std::copy_n(range.value, range.number, output_value + offset);
128 std::copy_n(range.index, range.number, output_index + offset);
130 }, primary, threads);
133 parallelize([&](
const int,
const InputIndex_ start,
const InputIndex_ length) ->
void {
137 for (InputIndex_ p = start, pe = start + length; p < pe; ++p) {
138 const auto ptr = wrk->fetch(buffer_v.data());
139 auto offset = pointers[p];
140 for (InputIndex_ s = 0; s < secondary; ++s) {
141 const auto val = ptr[s];
143 output_value[offset] = val;
144 output_index[offset] = s;
149 }, primary, threads);
153template<
typename InputValue_,
typename InputIndex_,
typename Po
inter_,
typename StoredValue_,
typename StoredIndex_>
154void fill_compressed_sparse_matrix_inconsistent(
156 const InputIndex_ primary,
157 const InputIndex_ secondary,
159 std::vector<Pointer_> offsets,
160 const std::optional<std::vector<InputIndex_> >& secondary_counts,
161 StoredValue_*
const output_value,
162 StoredIndex_*
const output_index,
165 fill_sparse_matrix_inconsistent(
171 [&](
const InputIndex_ s,
const SparseRange<InputValue_, InputIndex_>& range) ->
void {
172 for (InputIndex_ i = 0; i < range.number; ++i) {
173 auto& pos = offsets[range.index[i]];
174 output_value[pos] = range.value[i];
175 output_index[pos] = s;
179 [&](
const InputIndex_ s,
const InputValue_*
const ptr) ->
void {
180 for (InputIndex_ p = 0; p < primary; ++p) {
181 const auto val = ptr[p];
183 auto& pos = offsets[p];
184 output_value[pos] = val;
185 output_index[pos] = s;
190 [&](
const InputIndex_ s,
const std::vector<InputValue_>& cur_values,
const std::vector<InputIndex_>& cur_primary_indices) {
191 const auto cur_count = cur_values.size();
192 for (I<
decltype(cur_count)> i = 0; i < cur_count; ++i) {
193 auto& dest_pos = offsets[cur_primary_indices[i]];
194 output_value[dest_pos] = cur_values[i];
195 output_index[dest_pos] = s;
205struct FillCompressedSparseContentsOptions {
210template<
typename InputValue_,
typename InputIndex_,
typename Po
inter_,
typename StoredValue_,
typename StoredIndex_>
211void fill_compressed_sparse_contents(
214 const Pointer_*
const pointers,
215 StoredValue_*
const output_value,
216 StoredIndex_*
const output_index,
217 const FillCompressedSparseContentsOptions& options
219 const InputIndex_ NR = matrix.
nrow();
220 const InputIndex_ NC = matrix.
ncol();
221 const InputIndex_ primary = (row ? NR : NC);
222 const InputIndex_ secondary = (row ? NC : NR);
225 fill_compressed_sparse_matrix_consistent(matrix, primary, secondary, row, pointers, output_value, output_index, options.num_threads);
228 fill_compressed_sparse_matrix_inconsistent(
233 std::vector<Pointer_>(pointers, pointers + sanisizer::sum<std::size_t>(primary, 1)),
255template<
typename Value_,
typename Index_,
typename Po
inter_>
307template<
typename StoredValue_,
typename StoredIndex_,
typename StoredPo
inter_ = std::
size_t,
typename InputValue_,
typename InputIndex_>
316 auto& output_v = output.
value;
317 auto& output_i = output.
index;
320 const InputIndex_ NR = matrix.
nrow();
321 const InputIndex_ NC = matrix.
ncol();
322 const InputIndex_ primary = (row ? NR : NC);
323 const InputIndex_ secondary = (row ? NC : NR);
325 output_p.resize(sanisizer::sum<I<
decltype(output_p.size())> >(attest_for_Index(primary), 1));
329 const auto frag = retrieve_fragmented_sparse_contents_consistent<InputValue_, InputIndex_>(
339 if (use_rows == row) {
341 for (InputIndex_ p = 0; p < primary; ++p) {
342 output_p[p + 1] = sanisizer::sum<StoredPointer_>(output_p[p], frag.value[p].size());
345 output_v.reserve(output_p.back());
346 output_i.reserve(output_p.back());
347 for (InputIndex_ p = 0; p < primary; ++p) {
348 output_v.insert(output_v.end(), frag.value[p].begin(), frag.value[p].end());
349 output_i.insert(output_i.end(), frag.index[p].begin(), frag.index[p].end());
354 for (InputIndex_ s = 0; s < secondary; ++s) {
355 for (
const auto p : frag.index[s]) {
356 output_p[p + 1] += 1;
359 for (InputIndex_ p = 0; p < primary; ++p) {
360 output_p[p + 1] = sanisizer::sum<StoredPointer_>(output_p[p + 1], output_p[p]);
363 sanisizer::resize(output_v, output_p.back());
364 sanisizer::resize(output_i, output_p.back());
365 std::vector<StoredPointer_> offsets(output_p.begin(), output_p.begin() + primary);
366 for (InputIndex_ s = 0; s < secondary; ++s) {
367 const auto& cur_i = frag.index[s];
368 const auto& cur_v = frag.value[s];
369 const auto nnz = cur_i.size();
370 for (I<
decltype(nnz)> i = 0; i < nnz; ++i) {
371 auto& pos = offsets[cur_i[i]];
372 output_v[pos] = cur_v[i];
381 count_compressed_sparse_non_zeros_consistent(matrix, primary, secondary, row, output_p.data() + 1, options.
num_threads);
382 for (InputIndex_ i = 1; i <= primary; ++i) {
383 output_p[i] = sanisizer::sum<StoredPointer_>(output_p[i], output_p[i - 1]);
387 sanisizer::resize(output_v, output_p.back());
388 sanisizer::resize(output_i, output_p.back());
389 fill_compressed_sparse_matrix_consistent(
402 std::optional<std::vector<InputIndex_> > nnz_consistent;
403 count_sparse_non_zeros_inconsistent(matrix, primary, secondary, row, output_p.data() + 1, nnz_consistent, options.
num_threads);
404 for (InputIndex_ i = 1; i <= primary; ++i) {
405 output_p[i] = sanisizer::sum<StoredPointer_>(output_p[i], output_p[i - 1]);
409 sanisizer::resize(output_v, output_p.back());
410 sanisizer::resize(output_i, output_p.back());
411 fill_compressed_sparse_matrix_inconsistent(
464 typename StoredValue_ = Value_,
465 typename StoredIndex_ = Index_,
466 typename StoredPointer_ = std::size_t,
467 typename InputValue_,
485 return std::shared_ptr<Matrix<Value_, Index_> >(
489 std::vector<StoredValue_>,
490 std::vector<StoredIndex_>,
491 std::vector<StoredPointer_>
495 std::move(comp.value),
496 std::move(comp.index),
497 std::move(comp.pointers),
500 CompressedSparseMatrixOptions copt;
512template<
typename Value_,
typename Index_,
typename Count_>
514 return count_compressed_sparse_non_zeros(
519 CountCompressedSparseNonZerosOptions copt;
520 copt.num_threads = threads;
526template<
typename InputValue_,
typename InputIndex_,
typename Po
inter_,
typename StoredValue_,
typename StoredIndex_>
529 const Pointer_* pointers,
530 StoredValue_* output_value,
531 StoredIndex_* output_index,
534 fill_compressed_sparse_contents(
541 FillCompressedSparseContentsOptions fopt;
542 fopt.num_threads = threads;
548template<
typename StoredValue_,
typename StoredIndex_,
typename StoredPo
inter_ = std::
size_t,
typename InputValue_,
typename InputIndex_>
549CompressedSparseContents<StoredValue_, StoredIndex_, StoredPointer_>
retrieve_compressed_sparse_contents(
const Matrix<InputValue_, InputIndex_>* matrix,
bool row,
bool two_pass,
int threads = 1) {
554 RetrieveCompressedSparseContentsOptions opt;
555 opt.two_pass = two_pass;
556 opt.num_threads = threads;
562template<
typename Value_ =
double,
typename Index_ =
int,
typename StoredValue_ = Value_,
typename StoredIndex_ = Index_,
typename InputValue_,
typename InputIndex_>
563std::shared_ptr<Matrix<Value_, Index_> >
convert_to_compressed_sparse(
const Matrix<InputValue_, InputIndex_>* matrix,
bool row,
bool two_pass =
false,
int threads = 1) {
568 ConvertToCompressedSparseOptions opt;
569 opt.two_pass = two_pass;
570 opt.num_threads = threads;
576template <
bool row_,
typename Value_,
typename Index_,
typename InputValue_,
typename InputIndex_>
581template <
bool row_,
typename Value_,
typename Index_,
typename StoredValue_ = Value_,
typename StoredIndex_ = Index_,
typename InputValue_,
typename InputIndex_>
582std::shared_ptr<Matrix<Value_, Index_> >
convert_to_compressed_sparse(
const Matrix<InputValue_, InputIndex_>* matrix,
bool two_pass =
false,
int threads = 1) {
Compressed sparse matrix representation.
Convert index type to container size.
Compressed sparse matrix representation.
Definition CompressedSparseMatrix.hpp:580
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
Convert a matrix into a fragmented sparse format.
Copy data from one buffer to another.
Flexible representations for matrix data.
Definition Extractor.hpp:15
CompressedSparseContents< StoredValue_, StoredIndex_, StoredPointer_ > retrieve_compressed_sparse_contents(const Matrix< InputValue_, InputIndex_ > &matrix, const bool row, const RetrieveCompressedSparseContentsOptions &options)
Definition convert_to_compressed_sparse.hpp:308
int parallelize(Function_ fun, const Index_ tasks, const int workers)
Definition parallelize.hpp:58
Container_ create_container_of_Index_size(const Index_ x, Args_ &&... args)
Definition Index_to_container.hpp:82
std::shared_ptr< Matrix< Value_, Index_ > > convert_to_compressed_sparse(const Matrix< InputValue_, InputIndex_ > &matrix, const bool row, const ConvertToCompressedSparseOptions &options)
Definition convert_to_compressed_sparse.hpp:470
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.
Compressed sparse contents.
Definition convert_to_compressed_sparse.hpp:256
std::vector< Index_ > index
Definition convert_to_compressed_sparse.hpp:265
std::vector< Value_ > value
Definition convert_to_compressed_sparse.hpp:260
std::vector< Pointer_ > pointers
Definition convert_to_compressed_sparse.hpp:270
Options for convert_to_compressed_sparse().
Definition convert_to_compressed_sparse.hpp:430
bool two_pass
Definition convert_to_compressed_sparse.hpp:436
int num_threads
Definition convert_to_compressed_sparse.hpp:441
Options for retrieve_compressed_sparse_contents().
Definition convert_to_compressed_sparse.hpp:276
int num_threads
Definition convert_to_compressed_sparse.hpp:287
bool two_pass
Definition convert_to_compressed_sparse.hpp:282
Options for retrieve_fragmented_sparse_contents().
Definition convert_to_fragmented_sparse.hpp:65
int num_threads
Definition convert_to_fragmented_sparse.hpp:76