1#ifndef TATAMI_COMPRESS_SPARSE_TRIPLETS_H
2#define TATAMI_COMPRESS_SPARSE_TRIPLETS_H
4#include "../utils/Index_to_container.hpp"
12#include "sanisizer/sanisizer.hpp"
22namespace compress_triplets {
27template<
class Primary_,
class Secondary_>
28int is_ordered(
const Primary_& primary,
const Secondary_& secondary) {
29 if (!std::is_sorted(primary.begin(), primary.end())) {
33 auto nprimary = primary.size();
34 decltype(nprimary) start = 0;
35 while (start < nprimary) {
36 decltype(nprimary) end = start + 1;
37 while (end < nprimary && primary[end] == primary[start]) {
38 if (secondary[end] < secondary[end - 1]) {
50template<
typename Size_,
class Primary_,
class Secondary_>
51void order(
int status, std::vector<Size_>& indices,
const Primary_& primary,
const Secondary_& secondary) {
53 auto nprimary = primary.size();
54 decltype(nprimary) start = 0;
55 while (start < nprimary) {
56 decltype(nprimary) end = start + 1;
57 while (end < nprimary && primary[end] == primary[start]) {
62 if (!std::is_sorted(secondary.begin() + start, secondary.begin() + end)) {
63 std::sort(indices.begin() + start, indices.begin() + end, [&](Size_ left, Size_ right) ->
bool {
64 return secondary[left] < secondary[right];
70 }
else if (status == 2) {
71 std::sort(indices.begin(), indices.end(), [&](Size_ left, Size_ right) ->
bool {
72 if (primary[left] == primary[right]) {
73 return (secondary[left] < secondary[right]);
75 return (primary[left] < primary[right]);
105template<
class Values_,
class RowIndices_,
class ColumnIndices_>
106std::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) {
108 auto N = values.size();
109 if (!safe_non_negative_equal(N, row_indices.size()) || !safe_non_negative_equal(N, column_indices.size())) {
110 throw std::runtime_error(
"'row_indices', 'column_indices' and 'values' should have the same length");
113 int order_status = 0;
115 order_status = compress_triplets::is_ordered(row_indices, column_indices);
117 order_status = compress_triplets::is_ordered(column_indices, row_indices);
120 if (order_status != 0) {
121 auto indices = sanisizer::create<std::vector<
decltype(N)> >(N);
122 std::iota(indices.begin(), indices.end(),
static_cast<decltype(N)
>(0));
126 compress_triplets::order(order_status, indices, row_indices, column_indices);
128 compress_triplets::order(order_status, indices, column_indices, row_indices);
134 auto used = sanisizer::create<std::vector<unsigned char> >(N);
135 for (
decltype(N) i = 0; i < N; ++i) {
139 auto current = i, replacement = indices[i];
142 while (replacement != i) {
143 std::swap(row_indices[current], row_indices[replacement]);
144 std::swap(column_indices[current], column_indices[replacement]);
145 std::swap(values[current], values[replacement]);
147 current = replacement;
149 replacement = indices[replacement];
155 typedef std::vector<
decltype(N)> Output;
156 typedef typename Output::size_type OutputSize;
157 Output output(sanisizer::sum<OutputSize>(csr ? nrow : ncol, 1));
159 for (
auto t : row_indices) {
160 ++(output[
static_cast<OutputSize
>(t) + 1]);
163 for (
auto t : column_indices) {
164 ++(output[
static_cast<OutputSize
>(t) + 1]);
167 std::partial_sum(output.begin(), output.end(), output.begin());
176template<
bool row_,
class Values_,
class RowIndices_,
class ColumnIndices_>
177auto compress_sparse_triplets(std::size_t nrow, std::size_t ncol, Values_& values, RowIndices_& row_indices, ColumnIndices_& column_indices) {
178 return compress_sparse_triplets(nrow, ncol, values, row_indices, column_indices, row_);
Flexible representations for matrix data.
Definition Extractor.hpp:15
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:106