Using c++ upper_bound
with Rcpp
might be fast.
Rcpp::cppFunction(
"int upper_bound(double v, const Rcpp::NumericVector& x) {
return std::distance(x.begin(), std::upper_bound(x.begin(), x.end(), v));
}")
upper_bound(4, m)
#[1] 4
upper_bound(6, m)
#[1] 8
Benchmark:
set.seed(42)
n <- 1e6
m <- sort(rnorm(n, 0, 2))
bench::mark(which_min = c(which(abs(m-4) == min(abs(m-4))), which(abs(m-6) == min(abs(m-6))))
, which.max = c(which.max(m[m<=4]), which.max(m[m<=6]))
, length = c(length(m[m<=4]), length(m[m<=6]))
, max_which = c(max(which(m <= 4)), max(which(m <= 6)))
, sum = c(sum(m<=4), sum(m<=6))
, findIntervall = findInterval(c(4,6), m)
, CPP_upper_bound = c(upper_bound(4, m), upper_bound(6, m)))
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl>
#1 which_min 16.33ms 18.33ms 51.1 NA 55.0 26 28
#2 which.max 9.38ms 11.46ms 73.1 NA 101. 37 51
#3 length 8.41ms 10.06ms 79.7 NA 112. 40 56
#4 max_which 5.89ms 7.48ms 136. NA 67.8 68 34
#5 sum 2.68ms 3.33ms 274. NA 45.9 137 23
#6 findIntervall 679.33µs 788.1µs 1214. NA 0 607 0
#7 CPP_upper_bound 2.31µs 2.75µs 307024. NA 30.7 10000 1