1#ifndef TATAMI_COMPRESS_SPARSE_TRIPLETS_H 
    2#define TATAMI_COMPRESS_SPARSE_TRIPLETS_H 
   10#include "sanisizer/sanisizer.hpp" 
   12#include "../utils/Index_to_container.hpp" 
   26namespace compress_triplets {
 
   28template<
class Primary_, 
class Secondary_>
 
   29int is_ordered(
const Primary_& primary, 
const Secondary_& secondary) {
 
   30    if (!std::is_sorted(primary.begin(), primary.end())) {
 
   34    const auto nprimary = primary.size();
 
   35    I<
decltype(nprimary)> start = 0;
 
   36    while (start < nprimary) {
 
   37        I<
decltype(nprimary)> end = start + 1;
 
   38        while (end < nprimary && primary[end] == primary[start]) {
 
   39            if (secondary[end] < secondary[end - 1]) {
 
   51template<
typename Size_, 
class Primary_, 
class Secondary_>
 
   52void order(
const int status, std::vector<Size_>& indices, 
const Primary_& primary, 
const Secondary_& secondary) {
 
   54        const auto nprimary = primary.size();
 
   55        I<
decltype(nprimary)> start = 0;
 
   56        while (start < nprimary) {
 
   57            I<
decltype(nprimary)> end = start + 1;
 
   58            while (end < nprimary && primary[end] == primary[start]) {
 
   63            if (!std::is_sorted(secondary.begin() + start, secondary.begin() + end)) {
 
   65                    indices.begin() + start,
 
   66                    indices.begin() + end,
 
   67                    [&](
const Size_ left, 
const Size_ right) -> 
bool {
 
   68                        return secondary[left] < secondary[right];
 
   75    } 
else if (status == 2) {
 
   79            [&](
const Size_ left, 
const Size_ right) -> 
bool {
 
   80                if (primary[left] == primary[right]) {
 
   81                    return (secondary[left] < secondary[right]);
 
   83                return (primary[left] < primary[right]);
 
  122template<class Values_, typename Pointer_ = I<decltype(std::declval<Values_>().size())>, 
class PrimaryIndices_, 
class SecondaryIndices_>
 
  123std::vector<Pointer_> 
compress_sparse_triplets(std::size_t num_primary, Values_& values, 
const PrimaryIndices_& primary_indices, SecondaryIndices_& secondary_indices) {
 
  124    const auto N = values.size();
 
  125    if (!safe_non_negative_equal(N, primary_indices.size()) || !safe_non_negative_equal(N, secondary_indices.size())) {
 
  126        throw std::runtime_error(
"'primary_indices', 'secondary_indices' and 'values' should have the same length");
 
  129    const int order_status = compress_triplets::is_ordered(primary_indices, secondary_indices);
 
  130    if (order_status != 0) {
 
  131        auto indices = sanisizer::create<std::vector<I<
decltype(N)> > >(N);
 
  132        std::iota(indices.begin(), indices.end(), 
static_cast<I<decltype(N)
> >(0));
 
  133        compress_triplets::order(order_status, indices, primary_indices, secondary_indices);
 
  136        auto used = sanisizer::create<std::vector<unsigned char> >(N);
 
  137        for (I<
decltype(N)> i = 0; i < N; ++i) {
 
  141            auto current = i, replacement = indices[i];
 
  144            while (replacement != i) {
 
  145                std::swap(secondary_indices[current], secondary_indices[replacement]);
 
  146                std::swap(values[current], values[replacement]);
 
  147                current = replacement;
 
  149                replacement = indices[replacement];
 
  154    typedef std::vector<Pointer_> Output;
 
  155    typedef typename Output::size_type OutputSize;
 
  156    Output output(sanisizer::sum<OutputSize>(num_primary, 1));
 
  157    for (
const auto t : primary_indices) {
 
  158        ++(output[sanisizer::sum_unsafe<OutputSize>(t, 1)]);
 
  160    std::partial_sum(output.begin(), output.end(), output.begin());
 
 
  169template<
class Values_, 
class RowIndices_, 
class ColumnIndices_>
 
  170std::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) {
 
  172        auto output = compress_sparse_triplets(nrow, values, row_indices, column_indices);
 
  173        for (
decltype(nrow) r = 0; r < nrow; ++r) {
 
  174            std::fill_n(row_indices.begin() + output[r], output[r + 1] - output[r], r);
 
  179        for (
decltype(ncol) c = 0; c < ncol; ++c) {
 
  180            std::fill_n(column_indices.begin() + output[c], output[c + 1] - output[c], c);
 
  186template<
bool row_, 
class Values_, 
class RowIndices_, 
class ColumnIndices_>
 
  187auto compress_sparse_triplets(std::size_t nrow, std::size_t ncol, Values_& values, RowIndices_& row_indices, ColumnIndices_& column_indices) {
 
Copy data from one buffer to another.
 
Flexible representations for matrix data.
Definition Extractor.hpp:15
 
std::vector< Pointer_ > compress_sparse_triplets(std::size_t num_primary, Values_ &values, const PrimaryIndices_ &primary_indices, SecondaryIndices_ &secondary_indices)
Definition compress_sparse_triplets.hpp:123