diff --git a/cpp11test/src/test-doubles.cpp b/cpp11test/src/test-doubles.cpp index b17572b8..837103ee 100644 --- a/cpp11test/src/test-doubles.cpp +++ b/cpp11test/src/test-doubles.cpp @@ -3,6 +3,7 @@ #include "cpp11/doubles.hpp" #include "cpp11/function.hpp" #include "cpp11/integers.hpp" +#include "cpp11/logicals.hpp" #include "cpp11/sexp.hpp" #include "cpp11/strings.hpp" @@ -454,6 +455,22 @@ context("doubles-C++") { expect_true(!cpp11::is_na(na2[1])); } + test_that("as_doubles(logicals)") { + cpp11::writable::logicals y; + + for (int i = 0; i < 4; i++) { + y.push_back(i % 2 == 0); + } + + cpp11::doubles i(cpp11::as_doubles(y)); + + expect_true(i[0] == 1.0); + expect_true(i[1] == 0.0); + expect_true(i[2] == 1.0); + expect_true(i[3] == 0.0); + expect_true(cpp11::detail::r_typeof(i) == REALSXP); + } + test_that("doubles operator[] and at") { cpp11::doubles x(Rf_allocVector(REALSXP, 2)); REAL(x)[0] = 1; diff --git a/cpp11test/src/test-integers.cpp b/cpp11test/src/test-integers.cpp index bfc581bf..8caabdb6 100644 --- a/cpp11test/src/test-integers.cpp +++ b/cpp11test/src/test-integers.cpp @@ -2,6 +2,7 @@ #include "cpp11/doubles.hpp" #include "cpp11/function.hpp" #include "cpp11/integers.hpp" +#include "cpp11/logicals.hpp" #include "cpp11/strings.hpp" #include @@ -43,6 +44,22 @@ context("integers-C++") { expect_true(!cpp11::is_na(na2[1])); } + test_that("as_integers(logicals)") { + cpp11::writable::logicals y; + + for (int i = 0; i < 4; i++) { + y.push_back(i % 2 == 0); + } + + cpp11::integers i(cpp11::as_integers(y)); + + expect_true(i[0] == 1); + expect_true(i[1] == 0); + expect_true(i[2] == 1); + expect_true(i[3] == 0); + expect_true(cpp11::detail::r_typeof(i) == INTSXP); + } + test_that("integers.push_back()") { cpp11::writable::integers x; x.push_back(1); diff --git a/inst/include/cpp11/doubles.hpp b/inst/include/cpp11/doubles.hpp index dcab086d..647e3886 100644 --- a/inst/include/cpp11/doubles.hpp +++ b/inst/include/cpp11/doubles.hpp @@ -8,6 +8,7 @@ #include "cpp11/R.hpp" // for SEXP, SEXPREC, Rf_allocVector, REAL #include "cpp11/as.hpp" // for as_sexp #include "cpp11/protect.hpp" // for safe +#include "cpp11/r_bool.hpp" // for r_bool #include "cpp11/r_vector.hpp" // for vector, vector<>::proxy, vector<>::... #include "cpp11/sexp.hpp" // for sexp @@ -71,13 +72,12 @@ typedef r_vector doubles; } // namespace writable typedef r_vector integers; +typedef r_vector logicals; inline doubles as_doubles(SEXP x) { if (detail::r_typeof(x) == REALSXP) { return doubles(x); - } - - else if (detail::r_typeof(x) == INTSXP) { + } else if (detail::r_typeof(x) == INTSXP) { integers xn(x); size_t len = xn.size(); writable::doubles ret(len); @@ -85,6 +85,14 @@ inline doubles as_doubles(SEXP x) { return value == NA_INTEGER ? NA_REAL : static_cast(value); }); return ret; + } else if (detail::r_typeof(x) == LGLSXP) { + logicals xn(x); + size_t len = xn.size(); + writable::doubles ret(len); + std::transform(xn.begin(), xn.end(), ret.begin(), [](bool value) { + return value == NA_LOGICAL ? NA_REAL : static_cast(value); + }); + return ret; } throw type_error(REALSXP, detail::r_typeof(x)); diff --git a/inst/include/cpp11/integers.hpp b/inst/include/cpp11/integers.hpp index 68fd8e4d..b10d6e70 100644 --- a/inst/include/cpp11/integers.hpp +++ b/inst/include/cpp11/integers.hpp @@ -9,6 +9,7 @@ #include "cpp11/as.hpp" // for as_sexp #include "cpp11/attribute_proxy.hpp" // for attribute_proxy #include "cpp11/protect.hpp" // for safe +#include "cpp11/r_bool.hpp" // for r_bool #include "cpp11/r_vector.hpp" // for r_vector, r_vector<>::proxy #include "cpp11/sexp.hpp" // for sexp @@ -79,6 +80,7 @@ inline int na() { // forward declaration typedef r_vector doubles; +typedef r_vector logicals; inline integers as_integers(SEXP x) { if (detail::r_typeof(x) == INTSXP) { @@ -96,6 +98,14 @@ inline integers as_integers(SEXP x) { return static_cast(value); }); return ret; + } else if (detail::r_typeof(x) == LGLSXP) { + logicals xn(x); + size_t len = xn.size(); + writable::integers ret(len); + std::transform(xn.begin(), xn.end(), ret.begin(), [](bool value) { + return value == NA_LOGICAL ? NA_INTEGER : static_cast(value); + }); + return ret; } throw type_error(INTSXP, detail::r_typeof(x));