48template<
typename Output_,
typename Count_>
55 std::vector<Output_*>
mean;
62 std::vector<Output_*>
rss;
75template<
typename Value_,
typename Index_,
typename Group_,
typename Output_,
typename Count_>
79 const Group_*
const group,
80 const std::size_t num_groups,
84 const auto dim = (row ? mat.
nrow() : mat.
ncol());
85 const auto otherdim = (row ? mat.
ncol() : mat.
nrow());
88 auto full_group_sizes = sanisizer::create<std::vector<Index_> >(num_groups);
89 for (Index_ i = 0; i < otherdim; ++i) {
90 full_group_sizes[group[i]] += 1;
97 auto cur_means = sanisizer::create<std::vector<Output_> >(num_groups);
98 auto cur_rss = sanisizer::create<std::vector<Output_> >(num_groups);
99 auto cur_non_zeros = sanisizer::create<std::vector<Index_> >(num_groups);
100 auto cur_sizes = sanisizer::create<std::vector<Index_> >(num_groups);
102 for (Index_ x = 0; x < l; ++x) {
103 auto range = ext->fetch(vbuffer.data(), ibuffer.data());
106 for (Index_ i = 0; i <
range.number; ++i) {
107 const auto val =
range.value[i];
108 const auto b = group[
range.index[i]];
109 if (!std::isnan(val)) {
116 for (std::size_t g = 0; g < num_groups; ++g) {
117 const auto actual_size = full_group_sizes[g] - cur_sizes[g];
118 cur_sizes[g] = actual_size;
119 output.
count[g][s + x] = actual_size;
121 group_rss_finish_means(num_groups, cur_sizes.data(), cur_means,
static_cast<Index_
>(s + x), output.
mean);
124 for (Index_ i = 0; i <
range.number; ++i) {
125 const auto val =
range.value[i];
126 if (!std::isnan(val)) {
127 const auto g = group[
range.index[i]];
128 const auto delta = val - cur_means[g];
129 cur_rss[g] += delta * delta;
132 for (std::size_t g = 0; g < num_groups; ++g) {
133 if (cur_sizes[g] > 0) {
134 const Output_ my_rss = cur_rss[g] + cur_means[g] * cur_means[g] * (cur_sizes[g] - cur_non_zeros[g]);
135 output.
rss[g][s + x] = my_rss;
137 output.
rss[g][s + x] = 0;
141 std::fill(cur_means.begin(), cur_means.end(), 0);
142 std::fill(cur_rss.begin(), cur_rss.end(), 0);
143 std::fill(cur_non_zeros.begin(), cur_non_zeros.end(), 0);
144 std::fill(cur_sizes.begin(), cur_sizes.end(), 0);
152 auto cur_means = sanisizer::create<std::vector<Output_> >(num_groups);
153 auto cur_rss = sanisizer::create<std::vector<Output_> >(num_groups);
154 auto cur_sizes = sanisizer::create<std::vector<Index_> >(num_groups);
156 for (Index_ x = 0; x < l; ++x) {
157 auto ptr = ext->fetch(buffer.data());
160 for (Index_ j = 0; j < otherdim; ++j) {
161 const auto val = ptr[j];
162 if (!std::isnan(val)) {
163 const auto g = group[j];
168 for (std::size_t g = 0; g < num_groups; ++g) {
169 output.
count[g][s + x] = cur_sizes[g];
171 group_rss_finish_means(num_groups, cur_sizes.data(), cur_means,
static_cast<Index_
>(s + x), output.
mean);
174 for (Index_ j = 0; j < otherdim; ++j) {
175 const auto val = ptr[j];
176 if (!std::isnan(val)) {
177 const auto g = group[j];
178 const auto delta = val - cur_means[g];
179 cur_rss[g] += delta * delta;
182 for (std::size_t g = 0; g < num_groups; ++g) {
183 output.
rss[g][s + x] = cur_rss[g];
186 std::fill(cur_means.begin(), cur_means.end(), 0);
187 std::fill(cur_rss.begin(), cur_rss.end(), 0);
188 std::fill(cur_sizes.begin(), cur_sizes.end(), 0);
194template<
typename Value_,
typename Index_,
typename Group_,
typename Output_,
typename Count_>
195void group_rss_running(
198 const Group_*
const group,
199 const std::size_t num_groups,
200 GroupRssBuffers<Output_, Count_>& output,
201 const GroupRssOptions& opt
203 const auto dim = (row ? mat.
nrow() : mat.
ncol());
204 const auto otherdim = (row ? mat.
ncol() : mat.
nrow());
208 for (std::size_t g = 0; g < num_groups; ++g) {
209 std::fill_n(output.mean[g], dim, std::numeric_limits<Output_>::quiet_NaN());
210 std::fill_n(output.rss[g], dim, 0);
211 std::fill_n(output.count[g], dim, 0);
216 const bool do_parallel = opt.num_threads > 1;
217 std::optional<std::vector<std::optional<std::vector<std::vector<Output_> > > > > all_partial_mean, all_partial_rss;
218 std::optional<std::vector<std::optional<std::vector<std::vector<Count_> > > > > all_partial_count;
221 all_partial_rss.emplace(sanisizer::cast<I<
decltype(all_partial_rss->size())> >(opt.num_threads - 1));
222 all_partial_mean.emplace(sanisizer::cast<I<
decltype(all_partial_mean->size())> >(opt.num_threads));
223 all_partial_count.emplace(sanisizer::cast<I<
decltype(all_partial_count->size())> >(opt.num_threads));
226 for (std::size_t g = 0; g < num_groups; ++g) {
227 std::fill_n(output.mean[g], dim, 0);
228 std::fill_n(output.rss[g], dim, 0);
229 std::fill_n(output.count[g], dim, 0);
235 std::optional<std::vector<Output_*> > tmp_mean_ptrs, tmp_rss_ptrs;
236 std::optional<std::vector<std::vector<Output_> > > cur_mean, cur_rss;
238 std::optional<std::vector<Count_*> > tmp_count_ptrs;
239 std::optional<std::vector<std::vector<Count_> > > cur_count;
243 mean_ptrs = output.mean.data();
244 rss_ptrs = output.rss.data();
245 count_ptrs = output.count.data();
249 cur_mean.emplace(sanisizer::cast<I<
decltype(cur_mean->size())> >(num_groups));
250 tmp_mean_ptrs.emplace(sanisizer::cast<I<
decltype(tmp_mean_ptrs->size())> >(num_groups));
251 for (std::size_t g = 0; g < num_groups; ++g) {
253 (*tmp_mean_ptrs)[g] = (*cur_mean)[g].data();
255 mean_ptrs = tmp_mean_ptrs->data();
257 cur_count.emplace(sanisizer::cast<I<
decltype(cur_count->size())> >(num_groups));
258 tmp_count_ptrs.emplace(sanisizer::cast<I<
decltype(tmp_count_ptrs->size())> >(num_groups));
259 for (std::size_t g = 0; g < num_groups; ++g) {
261 (*tmp_count_ptrs)[g] = (*cur_count)[g].data();
263 count_ptrs = tmp_count_ptrs->data();
266 rss_ptrs = output.rss.data();
268 cur_rss.emplace(sanisizer::cast<I<
decltype(cur_rss->size())> >(num_groups));
269 tmp_rss_ptrs.emplace(sanisizer::cast<I<
decltype(tmp_rss_ptrs->size())> >(num_groups));
270 for (std::size_t g = 0; g < num_groups; ++g) {
272 (*tmp_rss_ptrs)[g] = (*cur_rss)[g].data();
274 rss_ptrs = tmp_rss_ptrs->data();
283 auto nonzeros = sanisizer::create<std::vector<std::vector<Count_> > >(num_groups);
284 std::vector<quickstats::RssRunningSparseSkip<Count_, Value_, Output_> > runners;
285 sanisizer::reserve(runners, num_groups);
286 for (std::size_t g = 0; g < num_groups; ++g) {
288 runners.emplace_back(dim, mean_ptrs[g], rss_ptrs[g], nonzeros[g].data(), count_ptrs[g]);
291 for (Index_ x = 0; x < l; ++x) {
292 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
293 runners[group[x + s]].add(
297 [](
const std::size_t,
const Value_ val) ->
bool {
298 return std::isnan(val);
303 for (std::size_t g = 0; g < num_groups; ++g) {
311 std::vector<quickstats::RssRunningDenseSkip<Count_, Value_, Output_> > runners;
312 sanisizer::reserve(runners, num_groups);
313 for (std::size_t g = 0; g < num_groups; ++g) {
314 runners.emplace_back(dim, mean_ptrs[g], rss_ptrs[g], count_ptrs[g]);
317 for (Index_ x = 0; x < l; ++x) {
318 auto out = ext->fetch(buffer.data());
319 runners[group[x + s]].add(
321 [](
const std::size_t,
const Value_ val) ->
bool {
322 return std::isnan(val);
327 for (std::size_t g = 0; g < num_groups; ++g) {
333 (*all_partial_count)[thread] = std::move(cur_count);
334 (*all_partial_mean)[thread] = std::move(cur_mean);
336 (*all_partial_rss)[thread - 1] = std::move(cur_rss);
339 }, otherdim, opt.num_threads);
343 const auto& ap_mean = *all_partial_mean;
344 const auto& ap_rss = *all_partial_rss;
345 const auto& ap_count = *all_partial_count;
347 for (std::size_t g = 0; g < num_groups; ++g) {
348 const auto cur_global_count = output.count[g];
349 for (
int u = 0; u < nused; ++u) {
350 const auto& cur_count = (*(ap_count[u]))[g];
351 for (Index_ d = 0; d < dim; ++d) {
352 cur_global_count[d] += cur_count[d];
358 for (std::size_t g = 0; g < num_groups; ++g) {
359 const auto cur_global_count = output.count[g];
360 const auto cur_global_mean = output.mean[g];
362 for (
int u = 0; u < nused; ++u) {
363 const auto& cur_mean = (*(ap_mean[u]))[g];
364 const auto& cur_count = (*(ap_count[u]))[g];
365 for (Index_ d = 0; d < dim; ++d) {
366 if (cur_count[d] > 0) {
367 const auto mult =
static_cast<Output_
>(cur_count[d]) /
static_cast<Output_
>(cur_global_count[d]);
368 cur_global_mean[d] += cur_mean[d] * mult;
373 for (Index_ d = 0; d < dim; ++d) {
374 if (cur_global_count[d] == 0) {
375 cur_global_mean[d] = std::numeric_limits<Output_>::quiet_NaN();
382 for (std::size_t g = 0; g < num_groups; ++g) {
383 const auto cur_global_mean = output.mean[g];
384 const auto cur_output = output.rss[g];
385 for (
int u = 0; u < nused; ++u) {
386 const auto& cur_mean = (*(ap_mean[u]))[g];
387 const auto& cur_count = (*(ap_count[u]))[g];
389 for (Index_ d = 0; d < dim; ++d) {
390 cur_output[d] = quickstats::recenter_rss(cur_count[d], cur_output[d], cur_mean[d], cur_global_mean[d]);
393 const auto& cur_rss = (*(ap_rss[u - 1]))[g];
394 for (Index_ d = 0; d < dim; ++d) {
395 cur_output[d] += quickstats::recenter_rss(cur_count[d], cur_rss[d], cur_mean[d], cur_global_mean[d]);
427template<
typename Value_,
typename Index_,
typename Group_,
typename Output_,
typename Count_>
431 const Group_*
const group,
432 const std::size_t num_groups,
436 assert(sanisizer::is_equal(num_groups, output.
mean.size()));
437 assert(sanisizer::is_equal(num_groups, output.
rss.size()));
438 assert(sanisizer::is_equal(num_groups, output.
count.size()));
440 group_rss_direct(row, mat, group, num_groups, output, opt);
442 group_rss_running(row, mat, group, num_groups, output, opt);
454template<
typename Output_,
typename Count_>
461 std::vector<std::vector<Output_> >
mean;
468 std::vector<std::vector<Output_> >
rss;
475 std::vector<std::vector<Count_> >
count;
499template<
typename Output_,
typename Count_,
typename Value_,
typename Index_,
typename Group_>
503 const Group_*
const group,
504 const std::size_t num_groups,
508 sanisizer::resize(output.
mean, num_groups);
509 sanisizer::resize(output.
rss, num_groups);
510 sanisizer::resize(output.
count, num_groups);
513 sanisizer::resize(buffers.
mean, num_groups);
514 sanisizer::resize(buffers.
rss, num_groups);
515 sanisizer::resize(buffers.
count, num_groups);
517 const auto dim = (row ? mat.
nrow() : mat.
ncol());
518 for (std::size_t g = 0; g < num_groups; ++g) {
520#ifdef TATAMI_STATS_TEST_DIRTY
524 buffers.
mean[g] = output.
mean[g].data();
527#ifdef TATAMI_STATS_TEST_DIRTY
531 buffers.
rss[g] = output.
rss[g].data();
534#ifdef TATAMI_STATS_TEST_DIRTY
541 group_rss(row, mat, group, num_groups, buffers, opt);