60template <
typename Sum_,
typename Detected_,
typename Float_>
98template <
typename Sum_,
typename Detected_,
typename Float_>
107 std::vector<std::vector<Sum_> >
sums;
131template<
bool sparse_,
typename Data_,
typename Index_,
typename Group_,
typename Sum_,
typename Detected_,
typename Float_>
132void aggregate_across_cells_by_row(
134 const Group_*
const group,
141 std::optional<std::vector<Index_> > group_sizes;
142 const auto NC = p.
ncol();
143 if (!buffers.
medians.empty()) {
144 group_sizes = tatami_stats::tabulate_groups(group, NC);
150 std::vector<Sum_> tmp_sums;
151 const auto nsums = buffers.
sums.size();
153 sanisizer::resize(tmp_sums, nsums);
156 std::vector<Detected_> tmp_detected;
157 const auto ndetected = buffers.
detected.size();
159 sanisizer::resize(tmp_detected, ndetected);
162 std::vector<std::vector<Float_> > tmp_medians;
163 const auto nmedians = buffers.
medians.size();
165 sanisizer::resize(tmp_medians, nmedians);
166 for (I<
decltype(nmedians)> l = 0; l < nmedians; ++l) {
167 sanisizer::reserve(tmp_medians[l], (*group_sizes)[l]);
171 const auto NC = p.
ncol();
174 if constexpr(sparse_) {
181 for (Index_ x = s, end = s + l; x < end; ++x) {
182 const auto row = [&]{
183 if constexpr(sparse_) {
184 return ext->fetch(vbuffer.data(), ibuffer.data());
186 return ext->fetch(vbuffer.data());
191 std::fill(tmp_sums.begin(), tmp_sums.end(), 0);
193 if constexpr(sparse_) {
194 for (Index_ j = 0; j < row.number; ++j) {
195 tmp_sums[group[row.index[j]]] += row.value[j];
198 for (Index_ j = 0; j < NC; ++j) {
199 tmp_sums[group[j]] += row[j];
204 for (I<
decltype(nsums)> l = 0; l < nsums; ++l) {
205 buffers.
sums[l][x] = tmp_sums[l];
210 std::fill(tmp_detected.begin(), tmp_detected.end(), 0);
212 if constexpr(sparse_) {
213 for (Index_ j = 0; j < row.number; ++j) {
214 tmp_detected[group[row.index[j]]] += (row.value[j] > 0);
217 for (Index_ j = 0; j < NC; ++j) {
218 tmp_detected[group[j]] += (row[j] > 0);
222 for (I<
decltype(ndetected)> l = 0; l < ndetected; ++l) {
223 buffers.
detected[l][x] = tmp_detected[l];
228 if constexpr(sparse_) {
229 for (Index_ j = 0; j < row.number; ++j) {
230 tmp_medians[group[row.index[j]]].push_back(row.value[j]);
232 for (I<
decltype(ndetected)> l = 0; l < nmedians; ++l) {
233 auto& current = tmp_medians[l];
234 buffers.
medians[l][x] = tatami_stats::medians::direct<Float_>(current.data(),
static_cast<Index_
>(current.size()), (*group_sizes)[l],
false);
239 for (Index_ j = 0; j < NC; ++j) {
240 tmp_medians[group[j]].push_back(row[j]);
242 for (I<
decltype(ndetected)> l = 0; l < nmedians; ++l) {
243 auto& current = tmp_medians[l];
244 buffers.
medians[l][x] = tatami_stats::medians::direct(current.data(), current.size(),
false);
253template<
bool sparse_,
typename Data_,
typename Index_,
typename Group_,
typename Sum_,
typename Detected_,
typename Float_>
254void aggregate_across_cells_by_column(
256 const Group_*
const group,
257 const AggregateAcrossCellsBuffers<Sum_, Detected_, Float_>& buffers,
258 const AggregateAcrossCellsOptions& options
262 assert(buffers.medians.empty());
265 const auto NC = p.
ncol();
269 if constexpr(sparse_) {
276 const auto num_sums = buffers.sums.size();
277 auto get_sum = [&](Index_ i) -> Sum_* {
return buffers.sums[i]; };
278 tatami_stats::LocalOutputBuffers<Sum_, I<
decltype(get_sum)>> local_sums(t, num_sums, start, length, std::move(get_sum));
280 const auto num_detected = buffers.detected.size();
281 auto get_detected = [&](Index_ i) -> Detected_* {
return buffers.detected[i]; };
282 tatami_stats::LocalOutputBuffers<Detected_, I<
decltype(get_detected)>> local_detected(t, num_detected, start, length, std::move(get_detected));
284 for (Index_ x = 0; x < NC; ++x) {
285 const auto current = group[x];
287 if constexpr(sparse_) {
288 const auto col = ext->fetch(vbuffer.data(), ibuffer.data());
290 const auto cursum = local_sums.data(current);
291 for (Index_ i = 0; i < col.number; ++i) {
292 cursum[col.index[i] - start] += col.value[i];
296 const auto curdetected = local_detected.data(current);
297 for (Index_ i = 0; i < col.number; ++i) {
298 curdetected[col.index[i] - start] += (col.value[i] > 0);
303 const auto col = ext->fetch(vbuffer.data());
305 const auto cursum = local_sums.data(current);
306 for (Index_ i = 0; i < length; ++i) {
311 const auto curdetected = local_detected.data(current);
312 for (Index_ i = 0; i < length; ++i) {
313 curdetected[i] += (col[i] > 0);
319 local_sums.transfer();
320 local_detected.transfer();
321 }, p.
nrow(), options.num_threads);
349template<
typename Data_,
typename Index_,
typename Group_,
typename Sum_,
typename Detected_,
typename Float_>
352 const Group_*
const group,
358 aggregate_across_cells_by_row<true>(input, group, buffers, options);
360 aggregate_across_cells_by_row<false>(input, group, buffers, options);
364 aggregate_across_cells_by_column<true>(input, group, buffers, options);
366 aggregate_across_cells_by_column<false>(input, group, buffers, options);
391template<
typename Sum_ =
double,
typename Detected_ =
int,
typename Float_ =
double,
typename Data_,
typename Index_,
typename Group_>
394 const Group_*
const group,
397 const Index_ NR = input.
nrow();
398 const Index_ NC = input.
ncol();
399 const std::size_t ngroups = [&]{
401 return sanisizer::sum<std::size_t>(*std::max_element(group, group + NC), 1);
403 return static_cast<std::size_t
>(0);
411 sanisizer::resize(output.
sums, ngroups);
412 sanisizer::resize(buffers.
sums, ngroups);
413 for (I<
decltype(ngroups)> l = 0; l < ngroups; ++l) {
414 auto& cursum = output.
sums[l];
416#ifdef SCRAN_AGGREGATE_TEST_INIT
417 , SCRAN_AGGREGATE_TEST_INIT
420 buffers.
sums[l] = cursum.data();
425 sanisizer::resize(output.
detected, ngroups);
426 sanisizer::resize(buffers.
detected, ngroups);
427 for (I<
decltype(ngroups)> l = 0; l < ngroups; ++l) {
430#ifdef SCRAN_AGGREGATE_TEST_INIT
431 , SCRAN_AGGREGATE_TEST_INIT
434 buffers.
detected[l] = curdet.data();
439 sanisizer::resize(output.
medians, ngroups);
440 sanisizer::resize(buffers.
medians, ngroups);
441 for (I<
decltype(ngroups)> l = 0; l < ngroups; ++l) {
442 auto& curdet = output.
medians[l];
444#ifdef SCRAN_AGGREGATE_TEST_INIT
445 , SCRAN_AGGREGATE_TEST_INIT
448 buffers.
medians[l] = curdet.data();