1#ifndef TATAMI_COMPRESS_SPARSE_TRIPLETS_H
2#define TATAMI_COMPRESS_SPARSE_TRIPLETS_H
20namespace compress_triplets {
25template<
class Primary_,
class Secondary_>
26int is_ordered(
const Primary_& primary,
const Secondary_& secondary) {
27 if (!std::is_sorted(primary.begin(), primary.end())) {
31 auto nprimary = primary.size();
32 decltype(nprimary) start = 0;
33 while (start < nprimary) {
34 decltype(nprimary) end = start + 1;
35 while (end < nprimary && primary[end] == primary[start]) {
36 if (secondary[end] < secondary[end - 1]) {
48template<
typename Size_,
class Primary_,
class Secondary_>
49void order(
int status, std::vector<Size_>& indices,
const Primary_& primary,
const Secondary_& secondary) {
51 auto nprimary = primary.size();
52 decltype(nprimary) start = 0;
53 while (start < nprimary) {
54 decltype(nprimary) end = start + 1;
55 while (end < nprimary && primary[end] == primary[start]) {
60 if (!std::is_sorted(secondary.begin() + start, secondary.begin() + end)) {
61 std::sort(indices.begin() + start, indices.begin() + end, [&](Size_ left, Size_ right) ->
bool {
62 return secondary[left] < secondary[right];
68 }
else if (status == 2) {
69 std::sort(indices.begin(), indices.end(), [&](Size_ left, Size_ right) ->
bool {
70 if (primary[left] == primary[right]) {
71 return (secondary[left] < secondary[right]);
73 return (primary[left] < primary[right]);
103template<
class Values_,
class RowIndices_,
class ColumnIndices_>
104std::vector<decltype(std::declval<Values_>().size())>
compress_sparse_triplets(std::size_t nrow, std::size_t ncol, Values_& values, RowIndices_& row_indices, ColumnIndices_& column_indices,
bool csr) {
106 auto N = values.size();
108 throw std::runtime_error(
"'row_indices', 'column_indices' and 'values' should have the same length");
111 int order_status = 0;
113 order_status = compress_triplets::is_ordered(row_indices, column_indices);
115 order_status = compress_triplets::is_ordered(column_indices, row_indices);
118 if (order_status != 0) {
119 std::vector<
decltype(N)> indices(N);
120 std::iota(indices.begin(), indices.end(),
static_cast<decltype(N)
>(0));
124 compress_triplets::order(order_status, indices, row_indices, column_indices);
126 compress_triplets::order(order_status, indices, column_indices, row_indices);
132 std::vector<unsigned char> used(N);
133 for (
decltype(N) i = 0; i < N; ++i) {
137 auto current = i, replacement = indices[i];
140 while (replacement != i) {
141 std::swap(row_indices[current], row_indices[replacement]);
142 std::swap(column_indices[current], column_indices[replacement]);
143 std::swap(values[current], values[replacement]);
145 current = replacement;
147 replacement = indices[replacement];
153 std::vector<
decltype(N)> output(csr ? nrow + 1 : ncol + 1);
155 for (
auto t : row_indices) {
159 for (
auto t : column_indices) {
163 std::partial_sum(output.begin(), output.end(), output.begin());
172template<
bool row_,
class Values_,
class RowIndices_,
class ColumnIndices_>
173auto compress_sparse_triplets(std::size_t nrow, std::size_t ncol, Values_& values, RowIndices_& row_indices, ColumnIndices_& column_indices) {
174 return compress_sparse_triplets(nrow, ncol, values, row_indices, column_indices, row_);
Sign-aware integer comparisons.
Flexible representations for matrix data.
Definition Extractor.hpp:15
bool safe_non_negative_equal(Left_ l, Right_ r)
Definition integer_comparisons.hpp:23
std::vector< decltype(std::declval< Values_ >().size())> compress_sparse_triplets(std::size_t nrow, std::size_t ncol, Values_ &values, RowIndices_ &row_indices, ColumnIndices_ &column_indices, bool csr)
Definition compress_sparse_triplets.hpp:104