58 Output_*
const output,
61 const auto left_NR = left.
nrow();
62 const auto common_dim = left.
ncol();
63 const auto right_NC = right.
ncol();
66 std::optional<std::vector<std::optional<std::vector<Output_> > > > tmp_results;
68 tmp_results.emplace(sanisizer::cast<I<
decltype(tmp_results->size())> >(options.
num_threads - 1));
71 std::fill_n(output, sanisizer::product_unsafe<std::size_t>(left_NR, right_NC), 0);
73 const int num_used =
tatami::parallelize([&](
int t, LeftIndex_ start, LeftIndex_ length) ->
void {
77 std::optional<std::vector<Output_> > tmp_output;
79 if (!do_parallel || t == 0) {
82 tmp_output.emplace(sanisizer::product<I<
decltype(tmp_output->size())> >(left_NR, right_NC));
83 outptr = tmp_output->data();
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());
96 if (lrange.number == 0 || rrange.number == 0) {
100 for (LeftIndex_ x = 0; x < lrange.number; ++x) {
101 const auto idx = lrange.index[x];
102 const Output_ mult = lrange.value[x];
103 for (RightIndex_ y = 0; y < rrange.number; ++y) {
104 outptr[sanisizer::nd_offset<std::size_t>(rrange.index[y], right_NC, idx)] += mult *
static_cast<Output_
>(rrange.value[y]);
109 if (do_parallel && t > 0) {
110 (*tmp_results)[t - 1] = std::move(tmp_output);
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) {
void multiply_sparse_column_with_sparse_row_matrix_to_row_output(const tatami::Matrix< LeftValue_, LeftIndex_ > &left, const tatami::Matrix< RightValue_, RightIndex_ > &right, Output_ *const output, const MultiplySparseColumnWithSparseRowMatrixToRowOutputOptions &options)
Definition row_to_row.hpp:55
auto consecutive_extractor(const Matrix< Value_, Index_ > &matrix, const bool row, const Index_ iter_start, const Index_ iter_length, Args_ &&... args)