110 template<
typename Float =
double,
typename Integer =
int>
239 compute_detected = s;
250 compute_max_count = s;
261 compute_max_index = s;
272 compute_subset_total = s;
283 compute_subset_detected = s;
312 template<
class Matrix,
typename Subset = const u
int8_t*>
313 Results run(
const Matrix* mat,
const std::vector<Subset>& subsets)
const {
316 auto ncells = mat->ncol();
319 output.
total.resize(ncells);
322 if (compute_detected) {
326 if (compute_max_index) {
330 if (compute_max_count) {
331 output.
max_count.resize(ncells, pick_fill_value<double>());
335 size_t nsubsets = subsets.size();
337 if (compute_subset_total) {
340 for (
size_t s = 0; s < nsubsets; ++s) {
346 if (compute_subset_detected) {
349 for (
size_t s = 0; s < nsubsets; ++s) {
356 run(mat, subsets, buffers);
362 static constexpr T pick_fill_value() {
363 if constexpr(std::numeric_limits<T>::has_infinity) {
364 return -std::numeric_limits<T>::infinity();
366 return std::numeric_limits<T>::lowest();
371 template<
typename Data_,
typename Index_,
typename Subset_,
typename Float_,
typename Integer_>
372 void compute_direct_dense(
const tatami::Matrix<Data_, Index_>* mat,
const std::vector<Subset_>& subsets, Buffers<Float_, Integer_>& output)
const {
373 std::vector<std::vector<int> > subset_indices;
374 if (!output.subset_total.empty() || !output.subset_detected.empty()) {
375 size_t nsubsets = subsets.size();
376 subset_indices.resize(nsubsets);
377 auto NR = mat->nrow();
379 for (
size_t s = 0; s < nsubsets; ++s) {
380 auto& current = subset_indices[s];
381 const auto& source = subsets[s];
383 for (
int i = 0; i < NR; ++i) {
385 current.push_back(i);
391 tatami::parallelize([&](
size_t, Index_ start, Index_ length) {
392 auto NR = mat->nrow();
393 auto ext = tatami::consecutive_extractor<false, false>(mat, start, length);
394 std::vector<Data_> vbuffer(NR);
395 bool do_max = output.max_index || output.max_count;
397 for (Index_ c = start, end = start + length; c < end; ++c) {
398 auto ptr = ext->fetch(c, vbuffer.data());
401 output.total[c] = std::accumulate(ptr, ptr + NR,
static_cast<Float_
>(0));
404 if (output.detected) {
406 for (Index_ r = 0; r < NR; ++r) {
407 count += (ptr[r] != 0);
409 output.detected[c] = count;
413 auto max_count = PerCellQcMetrics::pick_fill_value<Float_>();
414 Integer_ max_index = 0;
415 for (Index_ r = 0; r < NR; ++r) {
416 if (max_count < ptr[r]) {
422 if (output.max_index) {
423 output.max_index[c] = max_index;
425 if (output.max_count) {
426 output.max_count[c] = max_count;
430 size_t nsubsets = subset_indices.size();
431 for (
size_t s = 0; s < nsubsets; ++s) {
432 const auto& sub = subset_indices[s];
434 if (!output.subset_total.empty() && output.subset_total[s]) {
439 output.subset_total[s][c] = current;
442 if (!output.subset_detected.empty() && output.subset_detected[s]) {
443 Integer_ current = 0;
445 current += ptr[r] != 0;
447 output.subset_detected[s][c] = current;
451 }, mat->ncol(), num_threads);
454 template<
typename Data_,
typename Index_,
typename Subset_,
typename Float_,
typename Integer_>
455 void compute_direct_sparse(
const tatami::Matrix<Data_, Index_>* mat,
const std::vector<Subset_>& subsets, Buffers<Float_, Integer_>& output)
const {
457 opt.sparse_ordered_index =
false;
459 tatami::parallelize([&](
size_t, Index_ start, Index_ length) {
460 auto NR = mat->nrow();
461 auto ext = tatami::consecutive_extractor<false, true>(mat, start, length, opt);
462 std::vector<Data_> vbuffer(NR);
463 std::vector<Index_> ibuffer(NR);
465 bool do_max = output.max_index || output.max_count;
466 std::vector<unsigned char> internal_is_nonzero(output.max_index ? NR : 0);
468 for (Index_ c = start, end = start + length; c < end; ++c) {
469 auto range = ext->fetch(c, vbuffer.data(), ibuffer.data());
472 output.total[c] = std::accumulate(range.value, range.value + range.number,
static_cast<Float_
>(0));
475 if (output.detected) {
476 Integer_ current = 0;
477 for (Index_ i = 0; i < range.number; ++i) {
478 current += (range.value[i] != 0);
480 output.detected[c] = current;
484 auto max_count = PerCellQcMetrics::pick_fill_value<Float_>();
485 Integer_ max_index = 0;
486 for (Index_ i = 0; i < range.number; ++i) {
487 if (max_count < range.value[i]) {
488 max_count = range.value[i];
489 max_index = range.index[i];
493 if (max_count <= 0 && range.number < NR) {
502 if (output.max_index) {
503 for (Index_ i = 0; i < range.number; ++i) {
504 if (range.value[i]) {
505 internal_is_nonzero[range.index[i]] = 1;
508 for (Index_ r = 0; r < NR; ++r) {
509 if (internal_is_nonzero[r] == 0) {
514 for (Index_ i = 0; i < range.number; ++i) {
515 internal_is_nonzero[range.index[i]] = 0;
520 if (output.max_index) {
521 output.max_index[c] = max_index;
523 if (output.max_count) {
524 output.max_count[c] = max_count;
528 size_t nsubsets = subsets.size();
529 for (
size_t s = 0; s < nsubsets; ++s) {
530 const auto& sub = subsets[s];
532 if (!output.subset_total.empty() && output.subset_total[s]) {
533 auto& current = output.subset_total[s][c];
534 for (Index_ i = 0; i < range.number; ++i) {
535 current += (sub[range.index[i]] != 0) * range.value[i];
539 if (!output.subset_detected.empty() && output.subset_detected[s]) {
540 auto& current = output.subset_detected[s][c];
541 for (Index_ i = 0; i < range.number; ++i) {
542 current += (sub[range.index[i]] != 0) * (range.value[i] != 0);
547 }, mat->ncol(), num_threads);
550 template<
typename Data_,
typename Index_,
typename Subset_,
typename Float_,
typename Integer_>
551 void compute_running_dense(
const tatami::Matrix<Data_, Index_>* mat,
const std::vector<Subset_>& subsets, Buffers<Float_, Integer_>& output)
const {
552 tatami::parallelize([&](
size_t, Index_ start, Index_ len) {
553 auto NR = mat->nrow();
554 auto ext = tatami::consecutive_extractor<true, false>(mat, 0, NR, start, len);
555 std::vector<Data_> vbuffer(len);
556 bool do_max = output.max_index || output.max_count;
557 std::vector<Float_> internal_max_count(do_max && !output.max_count ? len : 0);
559 for (Index_ r = 0; r < NR; ++r) {
560 auto ptr = ext->fetch(r, vbuffer.data());
563 auto outt = output.total + start;
564 for (Index_ i = 0; i < len; ++i) {
569 if (output.detected) {
570 auto outd = output.detected + start;
571 for (Index_ i = 0; i < len; ++i) {
572 outd[i] += (ptr[i] != 0);
577 auto outmc = (output.max_count ? output.max_count + start : internal_max_count.data());
580 std::copy(ptr, ptr + len, outmc);
581 if (output.max_index) {
582 auto outmi = output.max_index + start;
583 std::fill(outmi, outmi + len, 0);
587 for (Index_ i = 0; i < len; ++i) {
588 auto& curmax = outmc[i];
589 if (curmax < ptr[i]) {
591 if (output.max_index) {
592 output.max_index[i + start] = r;
599 size_t nsubsets = subsets.size();
600 for (
size_t s = 0; s < nsubsets; ++s) {
601 const auto& sub = subsets[s];
606 if (!output.subset_total.empty() && output.subset_total[s]) {
607 auto current = output.subset_total[s] + start;
608 for (Index_ i = 0; i < len; ++i) {
609 current[i] += ptr[i];
613 if (!output.subset_detected.empty() && output.subset_detected[s]) {
614 auto current = output.subset_detected[s] + start;
615 for (Index_ i = 0; i < len; ++i) {
616 current[i] += (ptr[i] != 0);
621 }, mat->ncol(), num_threads);
624 template<
typename Data_,
typename Index_,
typename Subset_,
typename Float_,
typename Integer_>
625 void compute_running_sparse(
const tatami::Matrix<Data_, Index_>* mat,
const std::vector<Subset_>& subsets, Buffers<Float_, Integer_>& output)
const {
627 opt.sparse_ordered_index =
false;
629 Index_ NC = mat->ncol();
630 bool do_max = output.max_index || output.max_count;
631 std::vector<Float_> internal_max_count(do_max && !output.max_count ? NC : 0);
632 std::vector<Integer_> internal_last_consecutive_nonzero(do_max ? NC : 0);
634 tatami::parallelize([&](
size_t t, Index_ start, Index_ len) {
635 auto NR = mat->nrow();
636 auto ext = tatami::consecutive_extractor<true, true>(mat, 0, NR, start, len, opt);
637 std::vector<Data_> vbuffer(len);
638 std::vector<Index_> ibuffer(len);
640 for (Index_ r = 0; r < NR; ++r) {
641 auto range = ext->fetch(r, vbuffer.data(), ibuffer.data());
644 for (Index_ i = 0; i < range.number; ++i) {
645 output.total[range.index[i]] += range.value[i];
649 if (output.detected) {
650 for (Index_ i = 0; i < range.number; ++i) {
651 output.detected[range.index[i]] += (range.value[i] != 0);
656 auto outmc = (output.max_count ? output.max_count : internal_max_count.data());
658 for (Index_ i = 0; i < range.number; ++i) {
659 auto& curmax = outmc[range.index[i]];
660 if (curmax < range.value[i]) {
661 curmax = range.value[i];
662 if (output.max_index) {
663 output.max_index[range.index[i]] = r;
669 auto& last = internal_last_consecutive_nonzero[range.index[i]];
670 if (
static_cast<Index_
>(last) == r) {
671 if (range.value[i] != 0) {
678 size_t nsubsets = subsets.size();
679 for (
size_t s = 0; s < nsubsets; ++s) {
680 const auto& sub = subsets[s];
685 if (!output.subset_total.empty() && output.subset_total[s]) {
686 auto& current = output.subset_total[s];
687 for (
size_t i = 0; i < range.number; ++i) {
688 current[range.index[i]] += range.value[i];
692 if (!output.subset_detected.empty() && output.subset_detected[s]) {
693 auto& current = output.subset_detected[s];
694 for (
size_t i = 0; i < range.number; ++i) {
695 current[range.index[i]] += (range.value[i] != 0);
703 auto outmc = (output.max_count ? output.max_count : internal_max_count.data());
704 auto NR = mat->nrow();
708 for (Index_ c = 0; c < NC; ++c) {
709 auto& current = outmc[c];
714 auto last_nz = internal_last_consecutive_nonzero[c];
720 if (output.max_index) {
721 output.max_index[c] = last_nz;
740 template<
class Matrix,
typename Subset = const u
int8_t*,
typename Float,
typename Integer>
743 size_t n = mat->ncol();
744 auto check_and_fill = [&](
auto* ptr,
auto value) ->
void {
746 std::fill(ptr, ptr + n, value);
750 check_and_fill(output.
total,
static_cast<Float
>(0));
751 check_and_fill(output.
detected,
static_cast<Integer
>(0));
752 check_and_fill(output.
max_count, pick_fill_value<Float>());
753 check_and_fill(output.
max_index,
static_cast<Integer
>(0));
755 for (
size_t s = 0; s < subsets.size(); ++s) {
757 check_and_fill(output.
subset_total[s],
static_cast<Float
>(0));
766 if (mat->prefer_rows()) {
767 compute_running_sparse(mat, subsets, output);
769 compute_direct_sparse(mat, subsets, output);
772 if (mat->prefer_rows()) {
773 compute_running_dense(mat, subsets, output);
775 compute_direct_dense(mat, subsets, output);