tatami_mult
Multiply tatami matrices
Loading...
Searching...
No Matches
row_to_column.hpp
Go to the documentation of this file.
1#ifndef TATAMI_MULT_SPARSE_MATRIX_SPARSE_COLUMN_ROW_TO_COLUMN_HPP
2#define TATAMI_MULT_SPARSE_MATRIX_SPARSE_COLUMN_ROW_TO_COLUMN_HPP
3
4#include <cstddef>
5#include <vector>
6#include <optional>
7
8#include "tatami/tatami.hpp"
9#include "sanisizer/sanisizer.hpp"
10
11#include "../utils.hpp"
12#include "../../utils.hpp"
13
19namespace tatami_mult {
20
21/* See https://github.com/tatami-inc/test-multiplication/tree/master/sparse_column/sparse_matrix
22 * for an explanation of the choice of algorithm.
23 */
24
35
54template<typename LeftValue_, typename LeftIndex_, typename RightValue_, typename RightIndex_, typename Output_>
58 Output_* const output,
60) {
61 const auto left_NR = left.nrow();
62 const auto common_dim = left.ncol();
63 const auto right_NC = right.ncol();
64
65 const bool do_parallel = options.num_threads > 1;
66 std::optional<std::vector<std::optional<std::vector<Output_> > > > tmp_results;
67 if (do_parallel) {
68 tmp_results.emplace(sanisizer::cast<I<decltype(tmp_results->size())> >(options.num_threads - 1));
69 }
70
71 std::fill_n(output, sanisizer::product_unsafe<std::size_t>(left_NR, right_NC), 0);
72
73 const int num_used = tatami::parallelize([&](int t, LeftIndex_ start, LeftIndex_ length) -> void {
74 auto left_ext = tatami::consecutive_extractor<true>(left, false, start, length);
75 auto right_ext = tatami::consecutive_extractor<true>(right, true, start, length);
76
77 std::optional<std::vector<Output_> > tmp_output;
78 Output_* outptr;
79 if (!do_parallel || t == 0) {
80 outptr = output;
81 } else {
82 tmp_output.emplace(sanisizer::product<I<decltype(tmp_output->size())> >(left_NR, right_NC));
83 outptr = tmp_output->data();
84 }
85
90
91 for (LeftIndex_ cd = 0; cd < length; ++cd) {
92 const auto lrange = left_ext->fetch(left_vbuffer.data(), left_ibuffer.data());
93 const auto rrange = right_ext->fetch(right_vbuffer.data(), right_ibuffer.data());
94
95 // Skip should be after all fetch calls, otherwise extractors will go out of sync.
96 if (lrange.number == 0 || rrange.number == 0) {
97 continue;
98 }
99
100 for (RightIndex_ x = 0; x < rrange.number; ++x) {
101 const auto idx = rrange.index[x];
102 const Output_ mult = rrange.value[x];
103 for (LeftIndex_ y = 0; y < lrange.number; ++y) {
104 outptr[sanisizer::nd_offset<std::size_t>(lrange.index[y], left_NR, idx)] += mult * static_cast<Output_>(lrange.value[y]);
105 }
106 }
107 }
108
109 if (do_parallel && t > 0) {
110 (*tmp_results)[t - 1] = std::move(tmp_output);
111 }
112 }, common_dim, options.num_threads);
113
114 if (do_parallel) {
115 for (int u = 1; u < num_used; ++u) {
116 const auto& tmp = *((*tmp_results)[u - 1]);
117 const auto N = tmp.size();
118 for (I<decltype(N)> x = 0; x < N; ++x) {
119 output[x] += tmp[x];
120 }
121 }
122 }
123}
124
125}
126
127#endif
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
Multiplication of tatami matrices.
Definition column_to_column.hpp:19
void multiply_sparse_column_with_sparse_row_matrix_to_column_output(const tatami::Matrix< LeftValue_, LeftIndex_ > &left, const tatami::Matrix< RightValue_, RightIndex_ > &right, Output_ *const output, const MultiplySparseColumnWithSparseRowMatrixToColumnOutputOptions &options)
Definition row_to_column.hpp:55
int parallelize(Function_ fun, const Index_ tasks, const int workers)
Container_ create_container_of_Index_size(const Index_ x, Args_ &&... args)
auto consecutive_extractor(const Matrix< Value_, Index_ > &matrix, const bool row, const Index_ iter_start, const Index_ iter_length, Args_ &&... args)
Options for multiply_sparse_column_with_sparse_row_matrix_to_column_output().
Definition row_to_column.hpp:28