Skip to content

Commit 5fb3137

Browse files
authored
Feature converter ints doubles (#201)
1 parent 23ae34f commit 5fb3137

File tree

5 files changed

+101
-0
lines changed

5 files changed

+101
-0
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# cpp11 (development version)
2+
* added `as_double()` and `as_integer()` method to coerce integers to doubles and doubles to integers to doubles (@sbearrows, #46)
23
* Removed redundant `.Call calls` in cpp11.cpp file (@sbearrows, #170)
34
* Allow cpp11 decorators of the form `cpp11::linking_to` (@sbearrows, #193)
45

6+
57
# cpp11 0.3.1
68

79
* Fix stringop-truncation warning from generated wrapping code.

cpp11test/src/test-doubles.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <testthat.h>
22
#include <cstring>
33
#include "cpp11/doubles.hpp"
4+
#include "cpp11/integers.hpp"
45
#include "cpp11/sexp.hpp"
56
#include "cpp11/strings.hpp"
67

@@ -359,6 +360,26 @@ context("doubles-C++") {
359360
expect_true(cpp11::is_na(y));
360361
}
361362

363+
test_that("as_doubles(integers)") {
364+
cpp11::writable::integers y;
365+
y.push_back(10);
366+
y.push_back(13616);
367+
y.push_back(124);
368+
y.push_back(899);
369+
cpp11::doubles i(cpp11::as_doubles(y));
370+
371+
expect_true(i[0] == 10);
372+
expect_true(i[1] == 13616);
373+
expect_true(i[2] == 124);
374+
expect_true(i[3] == 899);
375+
expect_true(TYPEOF(i) == REALSXP);
376+
377+
cpp11::writable::strings e;
378+
e.push_back("a");
379+
e.push_back("b");
380+
expect_error(cpp11::as_doubles(e));
381+
}
382+
362383
test_that("doubles operator[] and at") {
363384
cpp11::doubles x(Rf_allocVector(REALSXP, 2));
364385
REAL(x)[0] = 1;

cpp11test/src/test-integers.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,41 @@
11
#include <testthat.h>
22
#include "Rversion.h"
3+
#include "cpp11/doubles.hpp"
34
#include "cpp11/integers.hpp"
5+
#include "cpp11/strings.hpp"
46

57
context("integers-C++") {
8+
test_that("as_integers(doubles)") {
9+
// TYPEOF(x) == INTSXP
10+
cpp11::writable::doubles y;
11+
y.push_back(10.00);
12+
cpp11::writable::integers i(cpp11::as_integers(y));
13+
expect_true(i[0] == 10);
14+
expect_true(TYPEOF(i) == INTSXP);
15+
16+
cpp11::writable::doubles x;
17+
x.push_back(10.01);
18+
expect_error(cpp11::as_integers(x));
19+
20+
cpp11::writable::strings e;
21+
e.push_back("a");
22+
e.push_back("b");
23+
expect_error(cpp11::as_integers(e));
24+
25+
cpp11::writable::doubles z;
26+
z.push_back(10);
27+
z.push_back(1000);
28+
z.push_back(100000);
29+
z.push_back(100000.00);
30+
31+
cpp11::writable::integers t((cpp11::as_integers(z)));
32+
expect_true(t[0] == 10);
33+
expect_true(t[1] == 1000);
34+
expect_true(t[2] == 100000);
35+
expect_true(t[3] == 100000);
36+
expect_true(TYPEOF(t) == INTSXP);
37+
}
38+
639
test_that("integers.push_back()") {
740
cpp11::writable::integers x;
841
x.push_back(1);

inst/include/cpp11/doubles.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,26 @@ typedef r_vector<double> doubles;
131131

132132
} // namespace writable
133133

134+
typedef r_vector<int> integers;
135+
136+
inline doubles as_doubles(sexp x) {
137+
if (TYPEOF(x) == REALSXP) {
138+
return as_cpp<doubles>(x);
139+
}
140+
141+
else if (TYPEOF(x) == INTSXP) {
142+
integers xn = as_cpp<integers>(x);
143+
size_t len = xn.size();
144+
writable::doubles ret;
145+
for (size_t i = 0; i < len; ++i) {
146+
ret.push_back(static_cast<double>(xn[i]));
147+
}
148+
return ret;
149+
}
150+
151+
throw type_error(INTSXP, TYPEOF(x));
152+
}
153+
134154
template <>
135155
inline double na() {
136156
return NA_REAL;

inst/include/cpp11/integers.hpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,29 @@ inline int na() {
141141
return NA_INTEGER;
142142
}
143143

144+
// forward declaration
145+
146+
typedef r_vector<double> doubles;
147+
148+
inline integers as_integers(sexp x) {
149+
if (TYPEOF(x) == INTSXP) {
150+
return as_cpp<integers>(x);
151+
} else if (TYPEOF(x) == REALSXP) {
152+
doubles xn = as_cpp<doubles>(x);
153+
size_t len = (xn.size());
154+
writable::integers ret = writable::integers(len);
155+
for (size_t i = 0; i < len; ++i) {
156+
double el = xn[i];
157+
if (!is_convertable_without_loss_to_integer(el)) {
158+
throw std::runtime_error("All elements must be integer-like");
159+
}
160+
ret[i] = (static_cast<int>(el));
161+
}
162+
163+
return ret;
164+
}
165+
166+
throw type_error(REALSXP, TYPEOF(x));
167+
}
168+
144169
} // namespace cpp11

0 commit comments

Comments
 (0)