62template <
typename Sum_,
typename Detected_,
typename Float_>
71 std::vector<Sum_*>
sum;
100template <
typename Sum_,
typename Detected_,
typename Float_>
109 std::vector<std::vector<Sum_> >
sum;
127 std::vector<std::vector<Float_> >
median;
133template<
typename Data_,
typename Index_,
typename Group_,
typename Sum_,
typename Detected_,
typename Float_>
134void aggregate_across_cells_by_row(
136 const Group_*
const group,
137 const std::size_t num_groups,
142 const auto NC = p.
ncol();
144 std::optional<std::vector<Index_> > group_sizes;
145 if (!buffers.
median.empty()) {
146 group_sizes.emplace(sanisizer::cast<I<
decltype(group_sizes->size())> >(num_groups));
147 for (Index_ c = 0; c < NC; ++c) {
148 (*group_sizes)[group[c]] += 1;
152 const auto nsum = buffers.
sum.size();
154 assert(nsum == num_groups);
157 const auto ndetected = buffers.
detected.size();
159 assert(ndetected == num_groups);
162 const auto nmedian = buffers.
median.size();
164 assert(nmedian == num_groups);
169 std::optional<std::vector<Sum_> > tmp_sum;
171 tmp_sum.emplace(sanisizer::cast<I<
decltype(tmp_sum->size())> >(nsum));
174 std::optional<std::vector<Detected_> > tmp_detected;
176 tmp_detected.emplace(sanisizer::cast<I<
decltype(tmp_detected->size())> >(ndetected));
179 std::optional<std::vector<std::vector<Float_> > > tmp_median;
181 tmp_median.emplace(sanisizer::cast<I<
decltype(tmp_median->size())> >(nmedian));
182 for (I<
decltype(nmedian)> l = 0; l < nmedian; ++l) {
183 sanisizer::reserve((*tmp_median)[l], (*group_sizes)[l]);
194 for (Index_ x = s, end = s + l; x < end; ++x) {
195 const auto row = ext->fetch(vbuffer.data(), ibuffer.data());
198 std::fill(tmp_sum->begin(), tmp_sum->end(), 0);
199 for (Index_ j = 0; j < row.number; ++j) {
200 (*tmp_sum)[group[row.index[j]]] += row.value[j];
202 for (I<
decltype(nsum)> l = 0; l < nsum; ++l) {
203 buffers.
sum[l][x] = (*tmp_sum)[l];
208 std::fill(tmp_detected->begin(), tmp_detected->end(), 0);
209 for (Index_ j = 0; j < row.number; ++j) {
210 (*tmp_detected)[group[row.index[j]]] += (row.value[j] > 0);
212 for (I<
decltype(ndetected)> l = 0; l < ndetected; ++l) {
213 buffers.
detected[l][x] = (*tmp_detected)[l];
218 quickstats::MedianOptions<Float_> medopt;
219 medopt.placeholder = std::numeric_limits<Float_>::quiet_NaN();
220 for (Index_ j = 0; j < row.number; ++j) {
221 (*tmp_median)[group[row.index[j]]].push_back(row.value[j]);
223 for (I<
decltype(ndetected)> l = 0; l < nmedian; ++l) {
224 auto& current = (*tmp_median)[l];
225 buffers.
median[l][x] = quickstats::median<Float_>((*group_sizes)[l], current.size(), current.data(), medopt);
234 for (Index_ x = s, end = s + l; x < end; ++x) {
235 const auto row = ext->fetch(vbuffer.data());
238 std::fill(tmp_sum->begin(), tmp_sum->end(), 0);
239 for (Index_ j = 0; j < NC; ++j) {
240 (*tmp_sum)[group[j]] += row[j];
242 for (I<
decltype(nsum)> l = 0; l < nsum; ++l) {
243 buffers.
sum[l][x] = (*tmp_sum)[l];
248 std::fill(tmp_detected->begin(), tmp_detected->end(), 0);
249 for (Index_ j = 0; j < NC; ++j) {
250 (*tmp_detected)[group[j]] += (row[j] > 0);
252 for (I<
decltype(ndetected)> l = 0; l < ndetected; ++l) {
253 buffers.
detected[l][x] = (*tmp_detected)[l];
258 quickstats::MedianOptions<Float_> medopt;
259 medopt.placeholder = std::numeric_limits<Float_>::quiet_NaN();
260 for (Index_ j = 0; j < NC; ++j) {
261 (*tmp_median)[group[j]].push_back(row[j]);
263 for (I<
decltype(ndetected)> l = 0; l < nmedian; ++l) {
264 auto& current = (*tmp_median)[l];
265 buffers.
median[l][x] = quickstats::median<Float_>(current.size(), current.data(), medopt);
275template<
typename Data_,
typename Index_,
typename Group_,
typename Sum_,
typename Detected_,
typename Float_>
276void aggregate_across_cells_by_column(
278 const Group_*
const group,
279 const std::size_t num_groups,
280 const AggregateAcrossCellsBuffers<Sum_, Detected_, Float_>& buffers,
281 const AggregateAcrossCellsOptions& options
284 const auto NR = p.
nrow();
285 assert(buffers.median.empty());
286 const bool do_parallel = options.num_threads > 1;
288 const auto nsum = buffers.sum.size();
289 std::optional<std::vector<std::optional<jiwoo::EquilengthArrays<Float_> > > > per_thread_sum;
291 assert(nsum == num_groups);
292 for (std::size_t g = 0; g < num_groups; ++g) {
293 std::fill_n(buffers.sum[g], NR, 0);
296 per_thread_sum.emplace(sanisizer::cast<I<
decltype(per_thread_sum->size())> >(options.num_threads - 1));
300 const auto ndetected = buffers.detected.size();
301 std::optional<std::vector<std::optional<jiwoo::EquilengthArrays<Detected_> > > > per_thread_detected;
303 assert(ndetected == num_groups);
304 for (std::size_t g = 0; g < num_groups; ++g) {
305 std::fill_n(buffers.detected[g], NR, 0);
308 per_thread_detected.emplace(sanisizer::cast<I<
decltype(per_thread_detected->size())> >(options.num_threads - 1));
312 const auto nused =
tatami::parallelize([&](
const int t,
const Index_ start,
const Index_ length) ->
void {
313 std::optional<jiwoo::EquilengthArrays<Float_> > tmp_sum;
314 std::optional<jiwoo::EquilengthArrays<Detected_> > tmp_detected;
316 Float_*
const * sum_ptrs = NULL;
317 Detected_*
const * det_ptrs = NULL;
321 sanisizer::cast<I<
decltype(tmp_sum->size())> >(num_groups),
322 static_cast<std::size_t
>(NR),
325 sum_ptrs = tmp_sum->get();
328 tmp_detected.emplace(
329 sanisizer::cast<I<
decltype(tmp_detected->size())> >(num_groups),
330 static_cast<std::size_t
>(NR),
333 det_ptrs = tmp_detected->get();
337 sum_ptrs = buffers.sum.data();
340 det_ptrs = buffers.detected.data();
351 for (Index_ x = 0; x < length; ++x) {
352 const auto col = ext->fetch(vbuffer.data(), ibuffer.data());
353 const auto curgroup = group[start + x];
356 const auto cursum = sum_ptrs[curgroup];
357 for (Index_ i = 0; i < col.number; ++i) {
358 cursum[col.index[i]] += col.value[i];
363 const auto curdetected = det_ptrs[curgroup];
364 for (Index_ i = 0; i < col.number; ++i) {
365 curdetected[col.index[i]] += (col.value[i] > 0);
374 for (Index_ x = 0; x < length; ++x) {
375 const auto col = ext->fetch(vbuffer.data());
376 const auto curgroup = group[start + x];
379 const auto cursum = sum_ptrs[curgroup];
380 for (Index_ i = 0; i < NR; ++i) {
386 const auto curdetected = det_ptrs[curgroup];
387 for (Index_ i = 0; i < NR; ++i) {
388 curdetected[i] += (col[i] > 0);
396 (*per_thread_sum)[t - 1] = std::move(tmp_sum);
399 (*per_thread_detected)[t - 1] = std::move(tmp_detected);
402 }, p.
ncol(), options.num_threads);
406 for (std::size_t g = 0; g < num_groups; ++g) {
407 const auto out = buffers.sum[g];
408 for (
int u = 1; u < nused; ++u) {
409 const auto ptrs = (*((*per_thread_sum)[u - 1]))[g];
410 for (Index_ r = 0; r < NR; ++r) {
418 for (std::size_t g = 0; g < num_groups; ++g) {
419 const auto out = buffers.detected[g];
420 for (
int u = 1; u < nused; ++u) {
421 const auto ptrs = (*((*per_thread_detected)[u - 1]))[g];
422 for (Index_ r = 0; r < NR; ++r) {
457template<
typename Data_,
typename Index_,
typename Group_,
typename Sum_,
typename Detected_,
typename Float_>
460 const Group_*
const group,
461 const std::size_t num_groups,
466 aggregate_across_cells_by_row(input, group, num_groups, buffers, options);
468 aggregate_across_cells_by_column(input, group, num_groups, buffers, options);
493template<
typename Sum_ =
double,
typename Detected_ =
int,
typename Float_ =
double,
typename Data_,
typename Index_,
typename Group_>
496 const Group_*
const group,
497 const std::size_t num_groups,
500 const Index_ NR = input.
nrow();
506 sanisizer::resize(output.
sum, num_groups);
507 sanisizer::resize(buffers.
sum, num_groups);
508 for (I<
decltype(num_groups)> l = 0; l < num_groups; ++l) {
509 auto& cursum = output.
sum[l];
511#ifdef SCRAN_AGGREGATE_TEST_INIT
512 , SCRAN_AGGREGATE_TEST_INIT
515 buffers.
sum[l] = cursum.data();
520 sanisizer::resize(output.
detected, num_groups);
521 sanisizer::resize(buffers.
detected, num_groups);
522 for (I<
decltype(num_groups)> l = 0; l < num_groups; ++l) {
525#ifdef SCRAN_AGGREGATE_TEST_INIT
526 , SCRAN_AGGREGATE_TEST_INIT
529 buffers.
detected[l] = curdet.data();
534 sanisizer::resize(output.
median, num_groups);
535 sanisizer::resize(buffers.
median, num_groups);
536 for (I<
decltype(num_groups)> l = 0; l < num_groups; ++l) {
537 auto& curmed = output.
median[l];
539#ifdef SCRAN_AGGREGATE_TEST_INIT
540 , SCRAN_AGGREGATE_TEST_INIT
543 buffers.
median[l] = curmed.data();