Skip to content

Instantly share code, notes, and snippets.

@artemklevtsov
Last active December 4, 2016 13:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artemklevtsov/5e1155551d90196adacb86ae80546588 to your computer and use it in GitHub Desktop.
Save artemklevtsov/5e1155551d90196adacb86ae80546588 to your computer and use it in GitHub Desktop.
rep functions family implementation
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::plugins(cpp11)]]
template <int RTYPE>
Vector<RTYPE> rep_each_impl(const Vector<RTYPE>& x, std::size_t each) {
std::size_t n = x.size();
Vector<RTYPE> res = no_init(n * each);
auto begin = res.begin();
for (std::size_t i = 0; i < n; begin += each, ++i)
std::fill(begin, begin + each, x[i]);
return res;
}
// [[Rcpp::export]]
SEXP rep_each(SEXP x, std::size_t each) {
RCPP_RETURN_VECTOR(rep_each_impl, x, each);
}
template <int RTYPE>
Vector<RTYPE> rep_times_impl(const Vector<RTYPE>& x, std::size_t times) {
std::size_t n = x.size();
Vector<RTYPE> res = no_init(n * times);
auto begin = x.begin(), end = x.end();
auto dest = res.begin();
for (std::size_t i = 0; i < times; dest += n, ++i)
std::copy(begin, end, dest);
return res;
}
// [[Rcpp::export]]
SEXP rep_times(SEXP x, std::size_t times) {
RCPP_RETURN_VECTOR(rep_times_impl, x, times);
}
template <int RTYPE>
Vector<RTYPE> rep_int_impl(const Vector<RTYPE>& x, const IntegerVector& times) {
std::size_t n = x.size(), ntimes = times.size();
if (n == ntimes) {
std::size_t n_out = std::accumulate(times.begin(), times.end(), 0);
Vector<RTYPE> res = no_init(n_out);
auto begin = res.begin();
for (std::size_t i = 0; i < n; begin += times[i], ++i)
std::fill(begin, begin + times[i], x[i]);
return res;
} else if (ntimes == 1) {
std::size_t n_out = n * times[0];
Vector<RTYPE> res = no_init(n_out);
auto start = x.begin(), end = x.end();
auto begin = res.begin();
for (std::size_t i = 0; i < times[0]; begin += n, ++i)
std::copy(start, end, begin);
return res;
} else {
stop("Invalid 'times' value");
}
return R_NilValue;
}
// [[Rcpp::export]]
SEXP rep_int(SEXP x, IntegerVector times) {
RCPP_RETURN_VECTOR(rep_int_impl, x, times);
}
/*** R
library(benchr)
identical2 <- function(...) { length(unique(list(...))) == 1L }
x <- 1:1000
n <- 1000
reps <- rep(length(x), n)
identical2(rep_each(x, n), rep(x, each = n), rep_int(x, reps), rep.int(x, reps))
benchmark(rep_each(x, n), rep(x, each = n), rep_int(x, reps), rep.int(x, reps))
identical2(rep_times(x, n), rep(x, times = n), rep_int(x, n), rep.int(x, n))
benchmark(rep_times(x, n), rep(x, times = n), rep_int(x, n), rep.int(x, n))
*/
@artemklevtsov
Copy link
Author

artemklevtsov commented Aug 6, 2016

R> library(benchr)

R> identical2 <- function(...) { length(unique(list(...))) == 1L }

R> x <- 1:1000

R> n <- 1000

R> reps <- rep(length(x), n)

R> identical2(rep_each(x, n), rep(x, each = n), rep_int(x, reps), rep.int(x, reps))
[1] TRUE

R> benchmark(rep_each(x, n), rep(x, each = n), rep_int(x, reps), rep.int(x, reps))
Benchmark summary:
Time units : microseconds 
             expr n.eval   min lw.qu median  mean up.qu   max   total relative
   rep_each(x, n)    100   293   332    368   547   430  1620   54700     1.00
 rep(x, each = n)    100 14000 14100  14100 14800 14200 64300 1480000    38.40
 rep_int(x, reps)    100   282   335    375   625   639  1590   62500     1.02
 rep.int(x, reps)    100   483   487    492   733   555  1840   73300     1.34

R> identical2(rep_times(x, n), rep(x, times = n), rep_int(x, n), rep.int(x, n))
[1] TRUE

R> benchmark(rep_times(x, n), rep(x, times = n), rep_int(x, n), rep.int(x, n))
Benchmark summary:
Time units : microseconds 
              expr n.eval min lw.qu median mean up.qu   max  total relative
   rep_times(x, n)    100 341   379    389  526   411  1620  52600     1.00
 rep(x, times = n)    100 919   922    928 1130   944  2220 113000     2.39
     rep_int(x, n)    100 342   378    392  549   431  1530  54900     1.01
     rep.int(x, n)    100 919   923    931 1660   959 51100 166000     2.39

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment