-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathas_double2.cpp
More file actions
75 lines (68 loc) · 1.96 KB
/
as_double2.cpp
File metadata and controls
75 lines (68 loc) · 1.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <Rcpp/Lightest>
// these two defines opt-into more extensive parsing support
#define FASTFLOAT_ALLOWS_LEADING_PLUS 1
#define FASTFLOAT_SKIP_WHITE_SPACE 1
#include "fast_float/fast_float.h"
/* essentially isBlankString(), but returns bool instead of Rboolean */
bool is_only_whitespace(const char *s) noexcept {
while (*s) {
if (!std::isspace(static_cast<unsigned char>(*s))) {
return false;
}
++s;
}
return true;
6804
div>
}
//' Ultra efficient string-to-\code{double} Conversion
//'
//' For \code{character} \code{vector}s, \code{as.double2()} is a
//' drop-in replacement for \code{base::as.double()}.
//'
//' @param x A vector of type \code{character}.
//'
//' @seealso \code{as.double()}
//'
//' @examples
//' set.seed(8675309)
//' input <- sample(c(
//' paste0(" \r\n\t\f\v", c(0.0, sqrt(seq(1, 10))), " \r\n\t\f\v"),
//' c("NaN", "-NaN", "nan", "-nan",
//' "Inf", "-Inf", "inf", "-inf", "infinity", "-infinity",
//' NA_character_,
//' " 1970-01-01", "1970-01-02 ")
//' ))
//' input
//'
//' suppressWarnings(as.double2(input)) # NAs introduced by coercion
//'
//' comparison <- suppressWarnings(
//' matrix(c(as.double(input), as.double2(input)),
//' ncol = 2L,
//' dimnames = list(NULL, c("as.double()", "as.double2()")))
//' )
//' comparison
//'
//' all.equal(comparison[, "as.double()"], comparison[, "as.double2()"])
//'
// [[Rcpp::export(as.double2)]]
Rcpp::DoubleVector
as_dbl(const Rcpp::CharacterVector x) {
const auto n{x.size()};
Rcpp::DoubleVector out(n, NA_REAL);
bool any_failures{false};
for (R_xlen_t i = 0; i < n; ++i) {
const char *cstring = CHAR(x[i]);
double d;
const auto res = fast_float::from_chars(
cstring, cstring + std::char_traits<char>::length(cstring), d);
if (res.ec == std::errc() && is_only_whitespace(res.ptr)) {
out[i] = d;
} else {
any_failures = true;
}
}
if (any_failures) {
Rcpp::warning("NAs introduced by coercion");
}
return out;
}