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);
113 if (medtmp == other) {
116 return medtmp + (other - medtmp) / 2;
138Output_
direct(Value_* value, Index_ num_nonzero, Index_ num_all,
bool skip_nan) {
142 if (num_nonzero == num_all) {
143 return direct<Output_>(value, num_all, skip_nan);
146 ::tatami_stats::internal::nanable_ifelse<Value_>(
149 auto lost = internal::translocate_nans(value, num_nonzero);
160 if (num_nonzero < num_all - num_nonzero) {
164 size_t halfway = num_all / 2;
165 bool is_even = (num_all % 2 == 0);
167 size_t num_zero = num_all - num_nonzero;
168 size_t num_negative = 0;
169 for (Index_ i = 0; i < num_nonzero; ++i) {
170 num_negative += (value[i] < 0);
174 if (num_negative > halfway) {
175 std::nth_element(value, value + halfway, value + num_nonzero);
176 return value[halfway];
178 }
else if (halfway >= num_negative + num_zero) {
179 size_t skip_zeros = halfway - num_zero;
180 std::nth_element(value, value + skip_zeros, value + num_nonzero);
181 return value[skip_zeros];
188 Output_ baseline = 0, other = 0;
189 if (num_negative > halfway) {
190 std::nth_element(value, value + halfway, value + num_nonzero);
191 baseline = value[halfway];
192 other = *(std::max_element(value, value + halfway));
194 }
else if (num_negative == halfway) {
195 size_t below_halfway = halfway - 1;
196 std::nth_element(value, value + below_halfway, value + num_nonzero);
197 other = value[below_halfway];
199 }
else if (num_negative < halfway && num_negative + num_zero > halfway) {
202 }
else if (num_negative + num_zero == halfway) {
203 size_t skip_zeros = halfway - num_zero;
204 std::nth_element(value, value + skip_zeros, value + num_nonzero);
205 other = value[skip_zeros];
208 size_t skip_zeros = halfway - num_zero;
209 std::nth_element(value, value + skip_zeros, value + num_nonzero);
210 baseline = value[skip_zeros];
211 other = *(std::max_element(value, value + skip_zeros));
214 if (baseline == other) {
217 return baseline + (other - baseline) / 2;
238 auto dim = (row ? p->
nrow() : p->
ncol());
239 auto otherdim = (row ? p->
ncol() : p->
nrow());
248 std::vector<Value_> buffer(otherdim);
249 auto vbuffer = buffer.data();
250 for (Index_ x = 0; x < l; ++x) {
251 auto range = ext->fetch(vbuffer, NULL);
253 output[x + s] = medians::direct<Output_>(vbuffer, range.number, otherdim, mopt.
skip_nan);
259 std::vector<Value_> buffer(otherdim);
261 for (Index_ x = 0; x < l; ++x) {
262 auto ptr = ext->fetch(buffer.data());
264 output[x + s] = medians::direct<Output_>(buffer.data(), otherdim, mopt.
skip_nan);