Skip to content

Commit d4e7c3f

Browse files
committed
vectorize multcomp_pmt
1 parent 7610d42 commit d4e7c3f

4 files changed

Lines changed: 61 additions & 74 deletions

File tree

R/Studentized.R

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,30 +60,32 @@ Studentized <- R6Class(
6060

6161
.define = function() {
6262
private$.statistic_func <- function(data, group) {
63+
i <- private$.group_ij$i
64+
j <- private$.group_ij$j
65+
6366
inv_lengths <- 1 / tabulate(group)
6467

65-
weights <- 1 / sqrt(outer(inv_lengths, inv_lengths, `+`))
68+
weights <- 1 / sqrt(inv_lengths[i] + inv_lengths[j])
6669

6770
if (private$.scoring == "none") {
68-
N <- length(data)
69-
k <- group[N]
71+
weights <- weights * sqrt(
72+
length(data) - length(inv_lengths)
73+
)
7074

7175
function(data, group) {
7276
means <- rowsum.default(data, group) * inv_lengths
7377

74-
weights_ <- weights / sqrt(
75-
sum((data - means[group])^2) / (N - k)
78+
(means[i] - means[j]) * weights / sqrt(
79+
sum((data - means[group])^2)
7680
)
77-
78-
function(i, j) (means[i] - means[j]) * weights_[i, j]
7981
}
8082
} else {
8183
weights <- weights / sd(data)
8284

8385
function(data, group) {
8486
means <- rowsum.default(data, group) * inv_lengths
8587

86-
function(i, j) (means[i] - means[j]) * weights[i, j]
88+
(means[i] - means[j]) * weights
8789
}
8890
}
8991
}

inst/include/pmt/impl_ksample_pmt.hpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,51 @@ RObject impl_ksample_pmt(
3535
}
3636
}
3737

38+
return static_cast<RObject>(statistic_container);
39+
}
40+
41+
template <bool progress, typename T>
42+
RObject impl_multcomp_pmt(
43+
const NumericVector data,
44+
IntegerVector group,
45+
T&& statistic_func,
46+
const double n_permu)
47+
{
48+
Stat<progress> statistic_container;
49+
50+
int c = C(*std::prev(group.end()), 2);
51+
52+
auto statistic_closure = statistic_func(data, group);
53+
auto multcomp_update = [&statistic_container, &statistic_closure, data, group, c]() {
54+
const double* statistic_ptr = statistic_closure(data, group);
55+
56+
for (int i = 1; i < c; i++) {
57+
statistic_container << *statistic_ptr++;
58+
}
59+
60+
return statistic_container << *statistic_ptr;
61+
};
62+
63+
statistic_container.allocate(c, n_permu != 0 ? n_permu : n_permutation(group));
64+
65+
#ifdef SETJMP
66+
SETJMP(statistic_func)
67+
#endif
68+
69+
multcomp_update();
70+
71+
if (!std::isnan(n_permu)) {
72+
statistic_container.switch_ptr();
73+
if (n_permu == 0) {
74+
do {
75+
multcomp_update();
76+
} while (next_permutation(group));
77+
} else {
78+
do {
79+
random_shuffle(group);
80+
} while (multcomp_update());
81+
}
82+
}
83+
3884
return static_cast<RObject>(statistic_container);
3985
}

inst/include/pmt/impl_multcomp_pmt.hpp

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/pmt_interface.cpp

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,8 @@ class CachedFunc : public Function {
2020
template <typename... Args>
2121
auto operator()(Args&&... args) const
2222
{
23-
return fast_invoker(Function::operator()(std::forward<Args>(args)...), std::forward<Args>(args)...);
24-
}
23+
Shield<SEXP> closure = Function::operator()(std::forward<Args>(args)...)
2524

26-
protected:
27-
template <typename... Args>
28-
auto fast_invoker(SEXP closure, Args&&... args) const
29-
{
3025
#if defined(R_VERSION) && R_VERSION >= R_Version(4, 5, 0)
3126
Shield<SEXP> closure_formals(R_ClosureFormals(closure)), closure_body(R_ClosureBody(closure)), closure_envir(R_ClosureEnv(closure));
3227
#else
@@ -96,22 +91,15 @@ SEXP ksample_pmt(
9691
impl_ksample_pmt<false, CachedFunc<double>>(data, clone(group), statistic_func, n_permu);
9792
}
9893

99-
#include "pmt/impl_multcomp_pmt.hpp"
100-
101-
template <typename T>
10294
class MultcompFunc : public CachedFunc<SEXP> {
10395
public:
10496
using CachedFunc<SEXP>::CachedFunc;
10597

10698
template <typename... Args>
10799
auto operator()(Args&&... args) const
108100
{
109-
return [statistic_closure = CachedFunc<SEXP>::operator()(std::forward<Args>(args)...), i = RObject(Rf_allocVector(INTSXP, 1)), j = RObject(Rf_allocVector(INTSXP, 1)), this](auto&&...) {
110-
return [pairwise_closure = this->fast_invoker(statistic_closure(), i, j), i_ptr = INTEGER(i), j_ptr = INTEGER(j)](int i, int j) {
111-
*i_ptr = i;
112-
*j_ptr = j;
113-
return as<T>(pairwise_closure());
114-
};
101+
return [statistic_closure = CachedFunc<SEXP>::operator()(std::forward<Args>(args)...)](auto&&... args) {
102+
return REAL(statistic_closure(std::forward<decltype(args)>(args)...));
115103
};
116104
}
117105
};
@@ -125,8 +113,8 @@ SEXP multcomp_pmt(
125113
const bool progress)
126114
{
127115
return progress ?
128-
impl_multcomp_pmt<true, MultcompFunc<double>>(data, clone(group), statistic_func, n_permu) :
129-
impl_multcomp_pmt<false, MultcompFunc<double>>(data, clone(group), statistic_func, n_permu);
116+
impl_multcomp_pmt<true, MultcompFunc>(data, clone(group), statistic_func, n_permu) :
117+
impl_multcomp_pmt<false, MultcompFunc>(data, clone(group), statistic_func, n_permu);
130118
}
131119

132120
#include "pmt/impl_paired_pmt.hpp"

0 commit comments

Comments
 (0)