1#ifndef TATAMI_MULT_MULTIPLE_VECTORS_SPARSE_COLUMN_HPP
2#define TATAMI_MULT_MULTIPLE_VECTORS_SPARSE_COLUMN_HPP
10#include "sanisizer/sanisizer.hpp"
11#include "jiwoo/jiwoo.hpp"
13#include "../utils.hpp"
14#include "../sparse_dot_product.hpp"
47template<
typename LeftValue_,
typename LeftIndex_,
typename RightVectors_,
typename GetRightVector_,
typename GetOutputVector_>
48void multiply_sparse_column_with_multiple_vectors_internal(
50 const LeftIndex_ start,
51 const LeftIndex_ length,
52 const LeftIndex_ left_NR,
53 const RightVectors_ right_vectors,
54 GetRightVector_ get_right_vector,
55 GetOutputVector_ get_output_vector,
59 typedef I<
decltype(get_output_vector(0)[0])> Output;
64 for (LeftIndex_ cd = 0; cd < length; ++cd) {
65 const auto range = ext->fetch(vbuffer.data(), ibuffer.data());
66 if (range.number == 0) {
70 for (RightVectors_ rv = 0; rv < right_vectors; ++rv) {
71 const auto optr = get_output_vector(rv);
72 const Output mult = get_right_vector(rv)[start + cd];
73 for (LeftIndex_ x = 0; x < range.number; ++x) {
74 optr[range.index[x]] += mult *
static_cast<Output
>(range.value[x]);
80 std::vector<std::vector<LeftValue_> > left_vbuffers;
81 std::vector<std::vector<LeftIndex_> > left_ibuffers;
82 std::vector<tatami::SparseRange<LeftValue_, LeftIndex_> > left_ranges;
83 std::vector<LeftIndex_> left_non_empty;
85 const LeftIndex_ max_block_cols = sanisizer::min(length, options.
block_size);
86 left_vbuffers.reserve(max_block_cols);
87 left_ibuffers.reserve(max_block_cols);
88 for (LeftIndex_ cd = 0; cd < max_block_cols; ++cd) {
92 sanisizer::resize(left_ranges, max_block_cols);
93 left_non_empty.reserve(max_block_cols);
101 const auto left_block_info = fetch_non_empty_sparse_block(
110 [](LeftIndex_) ->
void {}
112 const auto cd_num = left_block_info.num_non_empty;
116 if (left_block_info.all_non_empty) {
117 const LeftIndex_ cd_base = start + cd;
118 for (RightVectors_ rv = 0; rv < right_vectors; ++rv) {
119 const auto outvec = get_output_vector(rv);
120 const auto rightvec = get_right_vector(rv);
121 for (LeftIndex_ cd_counter = 0; cd_counter < cd_num; ++cd_counter) {
122 const auto& currange = left_ranges[cd_counter];
123 const Output mult = rightvec[cd_base + cd_counter];
124 for (LeftIndex_ x = 0; x < currange.number; ++x) {
125 outvec[currange.index[x]] += mult *
static_cast<Output
>(currange.value[x]);
131 for (
auto& cdne : left_non_empty) {
134 for (RightVectors_ rv = 0; rv < right_vectors; ++rv) {
135 const auto outvec = get_output_vector(rv);
136 const auto rightvec = get_right_vector(rv);
137 for (LeftIndex_ cd_counter = 0; cd_counter < cd_num; ++cd_counter) {
138 const auto& currange = left_ranges[cd_counter];
139 const Output mult = rightvec[left_non_empty[cd_counter]];
140 for (LeftIndex_ x = 0; x < currange.number; ++x) {
141 outvec[currange.index[x]] += mult *
static_cast<Output
>(currange.value[x]);
147 cd = left_block_info.position;
174template<
typename LeftValue_,
typename LeftIndex_,
typename RightVectors_,
typename GetRightVector_,
typename GetOutputVector_>
177 const RightVectors_ right_vectors,
178 GetRightVector_ get_right_vector,
179 GetOutputVector_ get_output_vector,
182 const auto left_NR = left.
nrow();
183 const auto common_dim = left.
ncol();
184 for (RightVectors_ rv = 0; rv < right_vectors; ++rv) {
185 std::fill_n(get_output_vector(rv), left_NR, 0);
189 typedef I<
decltype(get_output_vector(0)[0])> Output;
190 std::optional<std::vector<std::optional<std::vector<std::vector<Output> > > > > tmp_results;
192 tmp_results.emplace(sanisizer::cast<I<
decltype(tmp_results->size())> >(options.
num_threads - 1));
195 const auto num_used =
tatami::parallelize([&](
int t, LeftIndex_ start, LeftIndex_ length) ->
void {
196 if (!do_parallel || t == 0) {
197 multiply_sparse_column_with_multiple_vectors_internal(
209 std::vector<std::vector<Output> > tmp_output;
210 tmp_output.reserve(right_vectors);
211 for (RightVectors_ rv = 0; rv < right_vectors; ++rv) {
214 multiply_sparse_column_with_multiple_vectors_internal(
221 [&](
const RightVectors_ rv) -> Output* {
222 return tmp_output[rv].data();
226 (*tmp_results)[t - 1] = std::move(tmp_output);
231 for (
int u = 1; u < num_used; ++u) {
232 const auto& tmp = *((*tmp_results)[u - 1]);
233 for (RightVectors_ rv = 0; rv < right_vectors; ++rv) {
234 const auto& tmpvec = tmp[rv];
235 const auto outptr = get_output_vector(rv);
236 for (LeftIndex_ lr = 0; lr < left_NR; ++lr) {
237 outptr[lr] += tmpvec[lr];
259template<
typename LeftValue_,
typename LeftIndex_,
typename RightValue_,
typename Output_>
262 const std::vector<RightValue_*>& right,
263 const std::vector<Output_*>& output,
266 const auto left_NR = left.
nrow();
267 const auto common_dim = left.
ncol();
268 const auto right_vectors = right.size();
269 typedef I<
decltype(right_vectors)> RightVectors;
270 for (RightVectors rv = 0; rv < right_vectors; ++rv) {
271 std::fill_n(output[rv], left_NR, 0);
275 std::optional<std::vector<std::optional<jiwoo::EquilengthArrays<Output_> > > > tmp_results;
277 tmp_results.emplace(sanisizer::cast<I<
decltype(tmp_results->size())> >(options.
num_threads - 1));
280 const auto num_used =
tatami::parallelize([&](
int t, LeftIndex_ start, LeftIndex_ length) ->
void {
281 std::optional<jiwoo::EquilengthArrays<Output_> > tmp_output;
283 Output_*
const * output_ptrs;
284 if (!do_parallel || t == 0) {
285 output_ptrs = output.data();
288 sanisizer::cast<I<
decltype(tmp_output->size())> >(right_vectors),
289 static_cast<std::size_t
>(left_NR),
292 output_ptrs = tmp_output->get();
295 multiply_sparse_column_with_multiple_vectors_internal(
301 [&](
const RightVectors rv) ->
const RightValue_* {
304 [&](
const RightVectors rv) -> Output_* {
305 return output_ptrs[rv];
310 if (do_parallel && t > 0) {
311 (*tmp_results)[t - 1] = std::move(tmp_output);
316 for (
int u = 1; u < num_used; ++u) {
317 const auto& tmp = *((*tmp_results)[u - 1]);
318 for (RightVectors rv = 0; rv < right_vectors; ++rv) {
319 const auto tmpvec = tmp[rv];
320 const auto outptr = output[rv];
321 for (LeftIndex_ lr = 0; lr < left_NR; ++lr) {
322 outptr[lr] += tmpvec[lr];
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_multiple_vectors(const tatami::Matrix< LeftValue_, LeftIndex_ > &left, const RightVectors_ right_vectors, GetRightVector_ get_right_vector, GetOutputVector_ get_output_vector, const MultiplySparseColumnWithMultipleVectorsOptions &options)
Definition sparse_column.hpp:175
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_column_with_multiple_vectors().
Definition sparse_column.hpp:30
int num_threads
Definition sparse_column.hpp:35
int block_size
Definition sparse_column.hpp:41