68 Output_*
const output,
71 const auto left_NR = left.
nrow();
72 const auto common_dim = left.
ncol();
73 const auto right_NC = right.
ncol();
78 populate_sparse_buffers(
true, common_dim, right_NC, right, right_vbuffers, right_ibuffers, right_ranges, options.
num_threads);
81 auto right_non_empty = filter_non_empty_sparse(
83 [&](RightIndex_) ->
void {}
94 for (LeftIndex_ lr = 0; lr < length; ++lr) {
95 const auto lptr = ext->fetch(dbuffer.data());
97 auto loop_body = [&](LeftIndex_ cd) ->
void {
98 const auto rrange = right_ranges[cd];
99 const Output_ mult = lptr[cd];
100 for (RightIndex_ x = 0; x < rrange.number; ++x) {
101 tmp_row[rrange.index[x]] += mult *
static_cast<Output_
>(rrange.value[x]);
105 if (right_non_empty.has_value()) {
106 for (
const auto cd : *right_non_empty) {
110 for (LeftIndex_ cd = 0; cd < common_dim; ++cd) {
121 for (RightIndex_ rc = 0; rc < right_NC; ++rc) {
122 output[sanisizer::nd_offset<std::size_t>(start + lr, left_NR, rc)] = tmp_row[rc];
124 std::fill(tmp_row.begin(), tmp_row.end(), 0);
131 std::fill_n(output, sanisizer::product_unsafe<std::size_t>(left_NR, right_NC), 0);
137 const LeftIndex_ max_block_rows = sanisizer::min(length, options.
block_size);
138 std::vector<std::vector<LeftValue_> > lbuffers;
139 lbuffers.reserve(max_block_rows);
140 for (LeftIndex_ b = 0; b < max_block_rows; ++b) {
147 std::optional<std::vector<Output_> > tmp_cols;
149 tmp_cols.emplace(sanisizer::product<I<
decltype(tmp_cols->size())> >(max_block_rows, right_NC));
153 while (lr < length) {
154 const LeftIndex_ lr_num = sanisizer::min(options.
block_size, length - lr);
155 for (LeftIndex_ lr_counter = 0; lr_counter < lr_num; ++lr_counter) {
156 lptrs[lr_counter] = ext->fetch(lbuffers[lr_counter].data());
160 LeftIndex_ out_row_offset;
161 LeftIndex_ out_stride;
163 tmp_optr = tmp_cols->data();
168 out_row_offset = start + lr;
169 out_stride = left_NR;
172 auto loop_body = [&](LeftIndex_ cd) ->
void {
173 const auto rrange = right_ranges[cd];
177 for (LeftIndex_ lr_counter = 0; lr_counter < lr_num; ++lr_counter) {
178 colbuffer[lr_counter] = lptrs[lr_counter][cd];
181 for (RightIndex_ x = 0; x < rrange.number; ++x) {
182 const Output_ mult = rrange.value[x];
183 for (LeftIndex_ lr_counter = 0; lr_counter < lr_num; ++lr_counter) {
184 tmp_optr[sanisizer::nd_offset<std::size_t>(out_row_offset + lr_counter, out_stride, rrange.index[x])] += mult *
static_cast<Output_
>(colbuffer[lr_counter]);
189 if (right_non_empty.has_value()) {
190 for (
const auto cd : *right_non_empty) {
194 for (LeftIndex_ cd = 0; cd < common_dim; ++cd) {
200 for (RightIndex_ rc = 0; rc < right_NC; ++rc) {
201 const auto src = tmp_cols->data() + sanisizer::product_unsafe<std::size_t>(rc, lr_num);
202 std::copy_n(src, lr_num, output + sanisizer::nd_offset<std::size_t>(start + lr, left_NR, rc));
204 std::fill_n(tmp_cols->data(), sanisizer::product_unsafe<std::size_t>(right_NC, lr_num), 0);
void multiply_dense_row_with_sparse_row_matrix_to_column_output(const tatami::Matrix< LeftValue_, LeftIndex_ > &left, const tatami::Matrix< RightValue_, RightIndex_ > &right, Output_ *const output, const MultiplyDenseRowWithSparseRowMatrixToColumnOutputOptions &options)
Definition row_to_column.hpp:65