82Output_
direct(Value_* ptr, Index_ num,
bool skip_nan) {
83 ::tatami_stats::internal::nanable_ifelse<Value_>(
86 auto lost = internal::translocate_nans(ptr, num);
94 return std::numeric_limits<Output_>::quiet_NaN();
97 size_t halfway = num / 2;
98 bool is_even = (num % 2 == 0);
100 std::nth_element(ptr, ptr + halfway, ptr + num);
101 Output_ medtmp = *(ptr + halfway);
111 Output_ other = *std::max_element(ptr, ptr + halfway);
114 return medtmp + (other - medtmp)/2;
135Output_
direct(Value_* value, Index_ num_nonzero, Index_ num_all,
bool skip_nan) {
139 if (num_nonzero == num_all) {
140 return direct<Output_>(value, num_all, skip_nan);
143 ::tatami_stats::internal::nanable_ifelse<Value_>(
146 auto lost = internal::translocate_nans(value, num_nonzero);
157 if (num_nonzero < num_all - num_nonzero) {
161 size_t halfway = num_all / 2;
162 bool is_even = (num_all % 2 == 0);
164 size_t num_zero = num_all - num_nonzero;
165 size_t num_negative = 0;
166 for (Index_ i = 0; i < num_nonzero; ++i) {
167 num_negative += (value[i] < 0);
171 if (num_negative > halfway) {
172 std::nth_element(value, value + halfway, value + num_nonzero);
173 return value[halfway];
175 }
else if (halfway >= num_negative + num_zero) {
176 size_t skip_zeros = halfway - num_zero;
177 std::nth_element(value, value + skip_zeros, value + num_nonzero);
178 return value[skip_zeros];
185 Output_ baseline = 0, other = 0;
186 if (num_negative > halfway) {
187 std::nth_element(value, value + halfway, value + num_nonzero);
188 baseline = value[halfway];
189 other = *(std::max_element(value, value + halfway));
191 }
else if (num_negative == halfway) {
192 size_t below_halfway = halfway - 1;
193 std::nth_element(value, value + below_halfway, value + num_nonzero);
194 other = value[below_halfway];
196 }
else if (num_negative < halfway && num_negative + num_zero > halfway) {
199 }
else if (num_negative + num_zero == halfway) {
200 size_t skip_zeros = halfway - num_zero;
201 std::nth_element(value, value + skip_zeros, value + num_nonzero);
202 other = value[skip_zeros];
205 size_t skip_zeros = halfway - num_zero;
206 std::nth_element(value, value + skip_zeros, value + num_nonzero);
207 baseline = value[skip_zeros];
208 other = *(std::max_element(value, value + skip_zeros));
212 return baseline + (other - baseline) / 2;
232 auto dim = (row ? p->
nrow() : p->
ncol());
233 auto otherdim = (row ? p->
ncol() : p->
nrow());
242 std::vector<Value_> buffer(otherdim);
243 auto vbuffer = buffer.data();
244 for (Index_ x = 0; x < l; ++x) {
245 auto range = ext->fetch(vbuffer, NULL);
247 output[x + s] = medians::direct<Output_>(vbuffer, range.number, otherdim, mopt.
skip_nan);
253 std::vector<Value_> buffer(otherdim);
255 for (Index_ x = 0; x < l; ++x) {
256 auto ptr = ext->fetch(buffer.data());
258 output[x + s] = medians::direct<Output_>(buffer.data(), otherdim, mopt.
skip_nan);