Last active
January 31, 2021 18:43
-
-
Save knapply/38e1e3e718444b1733fa47cf61561dba to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// [[Rcpp::plugins(cpp17)]] | |
#include <Rcpp.h> | |
#include <fast_float/fast_float.h> | |
// [[Rcpp::depends(RcppFastFloat)]] | |
// [[Rcpp::export]] | |
SEXP fastfloat_s(Rcpp::CharacterVector invec) { | |
const auto n = invec.size(); | |
Rcpp::DoubleVector out(n, NA_REAL); | |
double d; | |
for (R_xlen_t i = 0; i < n; ++i) { | |
std::string s(invec[i]); | |
auto res = fast_float::from_chars(s.data(), s.data() + s.size(), d); | |
if (res.ec == std::errc()) { | |
out[i] = d; | |
} | |
} | |
return out; | |
} | |
// [[Rcpp::export]] | |
SEXP fastfloat_sv(Rcpp::CharacterVector invec) { | |
const auto n = invec.size(); | |
Rcpp::DoubleVector out(n, NA_REAL); | |
double d; | |
for (R_xlen_t i = 0; i < n; ++i) { | |
std::string_view s(invec[i]); | |
auto res = fast_float::from_chars(s.cbegin(), s.cend(), d); | |
if (res.ec == std::errc()) { | |
out[i] = d; | |
} | |
} | |
return out; | |
} | |
#ifdef __cpp_lib_string_view | |
#include <string_view> | |
#endif | |
// [[Rcpp::export(as.double2)]] | |
SEXP fastfloat2(const Rcpp::CharacterVector invec) { | |
const auto n = invec.size(); | |
Rcpp::DoubleVector out(n, NA_REAL); | |
double d; | |
bool any_failures = false; | |
for (R_xlen_t i = 0; i < n; ++i) { | |
#ifdef __cpp_lib_string_view | |
std::string_view s(invec[i]); | |
auto res = fast_float::from_chars(s.cbegin(), s.cend(), d); | |
#else | |
std::string s(invec[i]); | |
auto res = fast_float::from_chars(s.data(), s.data() + s.size(), d); | |
#endif | |
if (res.ec == std::errc()) { | |
out[i] = d; | |
} else { | |
any_failures = true; | |
} | |
} | |
if (any_failures) { | |
Rcpp::warning("NAs introduced by coercion"); | |
} | |
return out; | |
} | |
/*** R | |
N <- 1e6 | |
set.seed(42) | |
invec <- sample(sqrt(seq(1:N))) | |
input <- sample( | |
c(rep(c("junk1", "junk2", "more junk!"), N, replace=T), as.character(invec)) | |
) | |
suppressWarnings( | |
microbenchmark::microbenchmark( | |
as.double(input), | |
fastfloat_s(input), | |
fastfloat_sv(input), | |
as.double2(input), # same as fastfloat_sv, w/ warn on failures | |
check = "equal" | |
) | |
) | |
#> Unit: milliseconds | |
#> expr min lq mean median uq max neval | |
#> as.double(input) 779.2677 794.8253 815.7074 805.1494 836.4509 954.8745 100 | |
#> fastfloat_s(input) 201.6056 208.4925 229.3757 212.7901 245.5257 544.1641 100 | |
#> fastfloat_sv(input) 161.9853 168.6134 183.3555 171.3232 201.8738 487.4326 100 | |
#> as.double2(input) 161.8312 167.4808 186.2112 171.3153 201.8792 522.9541 100 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment