al-obrien / farrago

GNU General Public License v3.0
3 stars 0 forks source link

Allow varying thresholds in `accumulate_threshold` #1

Open al-obrien opened 7 months ago

al-obrien commented 7 months ago

Currently, accumulate_threshold only allows comparison to a scalar value. In some circumstances it could be useful to have each comparison made against a varied set of thresholds through time. As such, a numeric integer required. This could be done by allowing the threshold as a vector and indexing in the lambda. To ensure the vector is an appropriate size for comparison, can have a helper function in R, otherwise, the comparison can also be done right in C++

new_func <-
'std::vector<int>  accumulate_threshold2(NumericVector x, IntegerVector threshold) {
  // Initialize
  std::vector<int> out_vec;
  out_vec.reserve(x.length());

  if(threshold.length() > 1) {

  // Iterate with conditional lambda
  int indx = 0;
  std::accumulate(x.cbegin(),
                  x.cend(),
                  0,
                  [&out_vec, &indx, threshold](double x, double y){
                    int new_val = (x+y > threshold[indx]) ? 0 : x+y;
                    out_vec.push_back(new_val);
                    indx++;
                    //Rcout << "the value of indx: " << indx << "\\n";
                    return new_val;
                  });             

  } else {  
      // Iterate with conditional lambda
      std::accumulate(x.cbegin(),
                      x.cend(),
                      0,
                      [&out_vec, threshold](double x, double y){
                        int new_val = (x+y > threshold[0]) ? 0 : x+y;
                        out_vec.push_back(new_val);
                        return new_val;
                      });
  }
  return out_vec;
}'

# Compile
Rcpp::cppFunction(new_func , plugins=c("cpp11"))

# Add to within R helper for basic checks
new_func_wrapper <- function(x, y) {
    if(length(y) > 1 & length(y) != length(x)) stop('Unequal length of x and y, either have one threshold or a vector of same length')  
    accumulate_threshold2(x, y)
}

Check difference...

microbenchmark::microbenchmark(
  farrago::accumulate_threshold(seq(1,100, by = 3), 30),
  accumulate_threshold2(seq(1,100, by = 3), rep(30, 34)),
  accumulate_threshold2(seq(1,100, by = 3), 30),
  times = 10000, check = 'equal'
)