Skip to content

Commit

Permalink
Rewrote rel_diff in C++.
Browse files Browse the repository at this point in the history
  • Loading branch information
NicChr committed Nov 7, 2023
1 parent c0b894a commit b3c4eab
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 2 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: cppdoubles
Title: Fast Relative Comparisons of Floating Point Numbers in C++
Version: 0.1.0
Version: 0.1.0.9000
Authors@R:
person("Nick", "Christofides", , "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0002-9743-7342"))
Expand Down
4 changes: 4 additions & 0 deletions R/cpp11.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ cpp_double_lt_vectorised <- function(x, y, tolerance) {
cpp_double_lte_vectorised <- function(x, y, tolerance) {
.Call(`_cppdoubles_cpp_double_lte_vectorised`, x, y, tolerance)
}

cpp_rel_diff_vectorised <- function(x, y) {
.Call(`_cppdoubles_cpp_rel_diff_vectorised`, x, y)
}
2 changes: 1 addition & 1 deletion R/diff.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#' @rdname diff
#' @export
rel_diff <- function(x, y){
abs(x - y) / pmax(abs(x), abs(y))
.Call(`_cppdoubles_cpp_rel_diff_vectorised`, x, y)
}
#' @rdname diff
#' @export
Expand Down
8 changes: 8 additions & 0 deletions src/cpp11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ extern "C" SEXP _cppdoubles_cpp_double_lte_vectorised(SEXP x, SEXP y, SEXP toler
return cpp11::as_sexp(cpp_double_lte_vectorised(cpp11::as_cpp<cpp11::decay_t<SEXP>>(x), cpp11::as_cpp<cpp11::decay_t<SEXP>>(y), cpp11::as_cpp<cpp11::decay_t<SEXP>>(tolerance)));
END_CPP11
}
// cpp_doubles.cpp
SEXP cpp_rel_diff_vectorised(SEXP x, SEXP y);
extern "C" SEXP _cppdoubles_cpp_rel_diff_vectorised(SEXP x, SEXP y) {
BEGIN_CPP11
return cpp11::as_sexp(cpp_rel_diff_vectorised(cpp11::as_cpp<cpp11::decay_t<SEXP>>(x), cpp11::as_cpp<cpp11::decay_t<SEXP>>(y)));
END_CPP11
}

extern "C" {
static const R_CallMethodDef CallEntries[] = {
Expand All @@ -48,6 +55,7 @@ static const R_CallMethodDef CallEntries[] = {
{"_cppdoubles_cpp_double_gte_vectorised", (DL_FUNC) &_cppdoubles_cpp_double_gte_vectorised, 3},
{"_cppdoubles_cpp_double_lt_vectorised", (DL_FUNC) &_cppdoubles_cpp_double_lt_vectorised, 3},
{"_cppdoubles_cpp_double_lte_vectorised", (DL_FUNC) &_cppdoubles_cpp_double_lte_vectorised, 3},
{"_cppdoubles_cpp_rel_diff_vectorised", (DL_FUNC) &_cppdoubles_cpp_rel_diff_vectorised, 2},
{NULL, NULL, 0}
};
}
Expand Down
29 changes: 29 additions & 0 deletions src/cpp_doubles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,32 @@ SEXP cpp_double_lte_vectorised(SEXP x, SEXP y, SEXP tolerance) {
Rf_unprotect(1);
return out;
}

[[cpp11::register]]
SEXP cpp_rel_diff_vectorised(SEXP x, SEXP y) {
// double tolerance = std::sqrt(std::numeric_limits<double>::epsilon());
R_xlen_t x_len = Rf_xlength(x);
R_xlen_t y_len = Rf_xlength(y);
R_xlen_t n = std::max(x_len, y_len);
if (x_len <= 0 || y_len <= 0){
// Avoid loop if any are length zero vectors
n = 0;
}
double *p_x = REAL(x);
double *p_y = REAL(y);
SEXP out = Rf_protect(Rf_allocVector(REALSXP, n));
double *p_out = REAL(out);
R_xlen_t xi;
R_xlen_t yi;
for (R_xlen_t i = 0; i < n; ++i) {
xi = i % x_len;
yi = i % y_len;
p_out[i] = cpp_double_rel_diff(p_x[xi], p_y[yi]);
// If either is NA, out is NA
if ( cpp_double_is_na(p_x[xi]) || cpp_double_is_na(p_y[yi]) ){
p_out[i] = NA_REAL;
}
}
Rf_unprotect(1);
return out;
}

0 comments on commit b3c4eab

Please sign in to comment.