tatami_mult
Multiply tatami matrices
Loading...
Searching...
No Matches
row_to_row.hpp
Go to the documentation of this file.
1#ifndef TATAMI_MULT_DENSE_MATRIX_SPARSE_ROW_ROW_TO_ROW_HPP
2#define TATAMI_MULT_DENSE_MATRIX_SPARSE_ROW_ROW_TO_ROW_HPP
3
4#include <cstddef>
5#include <vector>
6#include <algorithm>
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_row/dense_matrix
22 * for an explanation of the choice of algorithm.
23 */
24
35
53template<typename LeftValue_, typename LeftIndex_, typename RightColumns_, class GetRightRow_, typename Output_>
56 const RightColumns_ right_columns,
57 GetRightRow_ get_right_row,
58 Output_* const output,
60) {
61 const auto left_NR = left.nrow();
62 const auto common_dim = left.ncol();
63
64 const bool do_parallel = options.num_threads > 1;
65 if (!do_parallel) {
66 std::fill_n(output, sanisizer::product_unsafe<std::size_t>(left_NR, right_columns), 0);
67 }
68
69 tatami::parallelize([&](int, LeftIndex_ start, LeftIndex_ length) -> void {
70 auto ext = tatami::consecutive_extractor<true>(left, true, start, length);
73
74 std::optional<std::vector<Output_> > tmp_output;
75 if (do_parallel) {
76 tmp_output.emplace(tatami::cast_Index_to_container_size<std::vector<Output_> >(right_columns));
77 }
78
79 for (LeftIndex_ lr = 0; lr < length; ++lr) {
80 const auto range = ext->fetch(vbuffer.data(), ibuffer.data());
81 const auto optr = output + sanisizer::product_unsafe<std::size_t>(start + lr, right_columns);
82 const auto tmp_optr = (do_parallel ? tmp_output->data() : optr);
83
84 for (LeftIndex_ x = 0; x < range.number; ++x) {
85 const auto rightrow = get_right_row(range.index[x]);
86 const auto mult = range.value[x];
87 for (RightColumns_ rc = 0; rc < right_columns; ++rc) {
88 tmp_optr[rc] += mult * rightrow[rc];
89 }
90 }
91
92 if (do_parallel) {
93 if (range.number == 0) {
94 // If it's empty, we would have never modified the temporary buffer,
95 // so we can proceed to directly zeroing the output array.
96 std::fill_n(optr, right_columns, 0);
97 } else {
98 std::copy_n(tmp_output->data(), right_columns, optr);
99 std::fill_n(tmp_output->data(), right_columns, 0);
100 }
101 }
102 }
103 }, left_NR, options.num_threads);
104}
105
126template<typename LeftValue_, typename LeftIndex_, typename RightValue_, typename RightIndex_, typename Output_>
130 Output_* const output,
132) {
133 const auto common_dim = left.ncol();
136 const auto right_NC = right.ncol();
137 populate_dense_buffers(true, common_dim, right_NC, right, right_buffers, right_ptrs, options.num_threads);
138
140 left,
141 right_NC,
142 [&](const LeftIndex_ cd) -> const RightValue_* {
143 return right_ptrs[cd];
144 },
145 output,
146 options
147 );
148}
149
150}
151
152#endif
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
Multiplication of tatami matrices.
Definition column_to_column.hpp:19
void multiply_sparse_row_with_dense_row_matrix_to_row_output(const tatami::Matrix< LeftValue_, LeftIndex_ > &left, const RightColumns_ right_columns, GetRightRow_ get_right_row, Output_ *const output, const MultiplySparseRowWithDenseRowMatrixToRowOutputOptions &options)
Definition row_to_row.hpp:54
int parallelize(Function_ fun, const Index_ tasks, const int workers)
I< decltype(std::declval< Container_ >().size())> cast_Index_to_container_size(const Index_ x)
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_row_with_dense_row_matrix_to_row_output().
Definition row_to_row.hpp:28