Rcpp::algorithm
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Introduction
A while back I saw a post on StackOverflow where the user was trying to use Rcpp::sugar::sum()
on an RcppParallel::RVector
.
Obviously this doesn’t work and it raised the question “Why doesn’t something more generic exist to provide functions with R
semantics that can be used on arbitrary data structures?” As a result, I set out to create a set of such functions following
the pattern of std::algorithm
in Rcpp::algorithm
.
Rcpp::algorithm
Currently Rcpp::algorithm
contains only a few simple functions, but if they are found to be useful, more will be added.
Examples of using the currently implemented iterator-based functions are below.
sum, sum_nona, prod, and prod_nona
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double sum_of_matrix_row(NumericMatrix m, int row) {
NumericMatrix::Row r = m.row(row);
return algorithm::sum(r.begin(), r.end());
}
min, max, and mean
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double mean_of_matrix_row(NumericMatrix m, int row) {
NumericMatrix::Row r = m.row(row);
return algorithm::mean(r.begin(), r.end());
}
log, exp, and sqrt
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector log_of_matrix_row(NumericMatrix m, int row) {
NumericMatrix::Row r = m.row(row);
NumericVector retval(m.cols());
algorithm::log(r.begin(), r.end(), retval.begin());
return retval;
}
Additional Benefits
Through the coding of these simple “algorithms”, a few needs arose.
First, the ability to deduce the appropriate C
numeric type
given an Rcpp
iterator was necessary. This gave birth to the Rcpp::algorithm::helpers::decays_to_ctype
and
Rcpp::algorithm::helpers::ctype
type traits. Given a type, these allow you to determine whether it can be cast to a C
numeric
type and which type that would be.
Second, the need arose for more information about R
types. This gave birth to the Rcpp::algorithm::helpers::rtype
traits. These
are defined as follows:
template< typename T >
struct rtype_helper {};
template<>
struct rtype_helper< double > {
typedef double type;
static RCPP_CONSTEXPR int RTYPE = REALSXP;
static inline double NA() { return NA_REAL; }
static inline RCPP_CONSTEXPR double ZERO() { return 0.0; }
static inline RCPP_CONSTEXPR double ONE() { return 1.0; }
};
template<>
struct rtype_helper< int > {
typedef int type;
static RCPP_CONSTEXPR int RTYPE = INTSXP;
static inline int NA() { return NA_INTEGER; }
static inline RCPP_CONSTEXPR int ZERO() { return 0; }
static inline RCPP_CONSTEXPR int ONE() { return 1; }
};
template< typename T >
struct rtype {
typedef typename rtype_helper< typename ctype< T >::type >::type type;
typedef rtype_helper< typename ctype< T >::type > helper_type;
static RCPP_CONSTEXPR int RTYPE = helper_type::RTYPE;
static inline T NA() { return helper_type::NA(); }
static inline RCPP_CONSTEXPR T ZERO() { return helper_type::ZERO(); }
static inline RCPP_CONSTEXPR T ONE() { return helper_type::ONE(); }
};
These additional benefits may actually prove more useful than the algorithms themselves. Only time will tell.
Wrapping Up
There are now some simple iterator-based algorithms that can be used with any structure that supports iterators. They apply the same semantics
as the analogous Rcpp::sugar
functions but give us more flexibility in their usage. If you find these to be useful, feel free to request more.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.