diff --git a/cpp11test/R/cpp11.R b/cpp11test/R/cpp11.R index 038e7b76..96d60062 100644 --- a/cpp11test/R/cpp11.R +++ b/cpp11test/R/cpp11.R @@ -88,6 +88,14 @@ cpp11_insert_ <- function(num_sxp) { .Call(`_cpp11test_cpp11_insert_`, num_sxp) } +ordered_map_to_list_ <- function(x) { + .Call(`_cpp11test_ordered_map_to_list_`, x) +} + +unordered_map_to_list_ <- function(x) { + .Call(`_cpp11test_unordered_map_to_list_`, x) +} + gibbs_cpp <- function(N, thin) { .Call(`_cpp11test_gibbs_cpp`, N, thin) } @@ -156,6 +164,34 @@ rcpp_release_ <- function(n) { invisible(.Call(`_cpp11test_rcpp_release_`, n)) } +notroxcpp1_ <- function(x) { + .Call(`_cpp11test_notroxcpp1_`, x) +} + +roxcpp2_ <- function(x) { + .Call(`_cpp11test_roxcpp2_`, x) +} + +roxcpp3_ <- function(x) { + .Call(`_cpp11test_roxcpp3_`, x) +} + +roxcpp4_ <- function(x) { + .Call(`_cpp11test_roxcpp4_`, x) +} + +roxcpp5_ <- function(x) { + .Call(`_cpp11test_roxcpp5_`, x) +} + +notroxcpp6_ <- function(x) { + .Call(`_cpp11test_notroxcpp6_`, x) +} + +roxcpp7_ <- function(x) { + .Call(`_cpp11test_roxcpp7_`, x) +} + cpp11_safe_ <- function(x_sxp) { .Call(`_cpp11test_cpp11_safe_`, x_sxp) } @@ -168,6 +204,26 @@ string_push_back_ <- function() { .Call(`_cpp11test_string_push_back_`) } +grow_strings_cpp11_ <- function(n, seed) { + .Call(`_cpp11test_grow_strings_cpp11_`, n, seed) +} + +grow_strings_rcpp_ <- function(n, seed) { + .Call(`_cpp11test_grow_strings_rcpp_`, n, seed) +} + +grow_strings_manual_ <- function(n, seed) { + .Call(`_cpp11test_grow_strings_manual_`, n, seed) +} + +assign_cpp11_ <- function(n, seed) { + .Call(`_cpp11test_assign_cpp11_`, n, seed) +} + +assign_rcpp_ <- function(n, seed) { + .Call(`_cpp11test_assign_rcpp_`, n, seed) +} + sum_dbl_for_ <- function(x) { .Call(`_cpp11test_sum_dbl_for_`, x) } @@ -236,6 +292,14 @@ rcpp_push_and_truncate_ <- function(size_sxp) { .Call(`_cpp11test_rcpp_push_and_truncate_`, size_sxp) } +nullable_extptr_1 <- function() { + .Call(`_cpp11test_nullable_extptr_1`) +} + +nullable_extptr_2 <- function() { + .Call(`_cpp11test_nullable_extptr_2`) +} + test_destruction_inner <- function() { invisible(.Call(`_cpp11test_test_destruction_inner`)) } diff --git a/cpp11test/man/roxcpp2_.Rd b/cpp11test/man/roxcpp2_.Rd new file mode 100644 index 00000000..dd000a0f --- /dev/null +++ b/cpp11test/man/roxcpp2_.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cpp11.R +\name{roxcpp2_} +\alias{roxcpp2_} +\title{Roxygenise C++ function II} +\usage{ +roxcpp2_(x) +} +\arguments{ +\item{x}{numeric value} +} +\description{ +Dummy function to test roxygen2. It adds 2.0 to a double. +} +\examples{ +roxcpp2_(1.0) +} diff --git a/cpp11test/man/roxcpp3_.Rd b/cpp11test/man/roxcpp3_.Rd new file mode 100644 index 00000000..3d31d143 --- /dev/null +++ b/cpp11test/man/roxcpp3_.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cpp11.R +\name{roxcpp3_} +\alias{roxcpp3_} +\title{Roxygenise C++ function III} +\usage{ +roxcpp3_(x) +} +\arguments{ +\item{x}{numeric value} +} +\description{ +Dummy function to test roxygen2. It adds 3.0 to a double. +} +\examples{ +roxcpp3_(1.0) +} diff --git a/cpp11test/man/roxcpp4_.Rd b/cpp11test/man/roxcpp4_.Rd new file mode 100644 index 00000000..f9cbb022 --- /dev/null +++ b/cpp11test/man/roxcpp4_.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cpp11.R +\name{roxcpp4_} +\alias{roxcpp4_} +\title{Roxygenise C++ function IV} +\usage{ +roxcpp4_(x) +} +\arguments{ +\item{x}{numeric value} +} +\description{ +Dummy function to test roxygen2. It adds 4.0 to a double. +} +\examples{ +roxcpp4_(1.0) +} diff --git a/cpp11test/man/roxcpp5_.Rd b/cpp11test/man/roxcpp5_.Rd new file mode 100644 index 00000000..ada8f9ee --- /dev/null +++ b/cpp11test/man/roxcpp5_.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cpp11.R +\name{roxcpp5_} +\alias{roxcpp5_} +\title{Roxygenise C++ function V} +\usage{ +roxcpp5_(x) +} +\arguments{ +\item{x}{numeric value} +} +\description{ +Dummy function to test roxygen2. It adds 5.0 to a double. +} +\examples{ +roxcpp5_(1.0) +} diff --git a/cpp11test/man/roxcpp7_.Rd b/cpp11test/man/roxcpp7_.Rd new file mode 100644 index 00000000..17466bf6 --- /dev/null +++ b/cpp11test/man/roxcpp7_.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cpp11.R +\name{roxcpp7_} +\alias{roxcpp7_} +\title{Roxygenise C++ function VII} +\usage{ +roxcpp7_(x) +} +\arguments{ +\item{x}{numeric value} +} +\description{ +Dummy function to test roxygen2. It adds 7.0 to a double. +} +\examples{ +my_fun <- function(x) { + roxcpp7_(x) +} +} +\seealso{ +\code{\link{roxcpp1_}} +} diff --git a/cpp11test/src/cpp11.cpp b/cpp11test/src/cpp11.cpp index 421de637..56057fc0 100644 --- a/cpp11test/src/cpp11.cpp +++ b/cpp11test/src/cpp11.cpp @@ -173,6 +173,20 @@ extern "C" SEXP _cpp11test_cpp11_insert_(SEXP num_sxp) { return cpp11::as_sexp(cpp11_insert_(cpp11::as_cpp>(num_sxp))); END_CPP11 } +// map.cpp +SEXP ordered_map_to_list_(cpp11::doubles x); +extern "C" SEXP _cpp11test_ordered_map_to_list_(SEXP x) { + BEGIN_CPP11 + return cpp11::as_sexp(ordered_map_to_list_(cpp11::as_cpp>(x))); + END_CPP11 +} +// map.cpp +SEXP unordered_map_to_list_(cpp11::doubles x); +extern "C" SEXP _cpp11test_unordered_map_to_list_(SEXP x) { + BEGIN_CPP11 + return cpp11::as_sexp(unordered_map_to_list_(cpp11::as_cpp>(x))); + END_CPP11 +} // matrix.cpp SEXP gibbs_cpp(int N, int thin); extern "C" SEXP _cpp11test_gibbs_cpp(SEXP N, SEXP thin) { @@ -500,6 +514,7 @@ static const R_CallMethodDef CallEntries[] = { {"_cpp11test_my_warning_n1", (DL_FUNC) &_cpp11test_my_warning_n1, 1}, {"_cpp11test_my_warning_n1fmt", (DL_FUNC) &_cpp11test_my_warning_n1fmt, 1}, {"_cpp11test_my_warning_n2fmt", (DL_FUNC) &_cpp11test_my_warning_n2fmt, 2}, + {"_cpp11test_ordered_map_to_list_", (DL_FUNC) &_cpp11test_ordered_map_to_list_, 1}, {"_cpp11test_protect_many_", (DL_FUNC) &_cpp11test_protect_many_, 1}, {"_cpp11test_protect_many_cpp11_", (DL_FUNC) &_cpp11test_protect_many_cpp11_, 1}, {"_cpp11test_protect_many_preserve_", (DL_FUNC) &_cpp11test_protect_many_preserve_, 1}, @@ -533,6 +548,7 @@ static const R_CallMethodDef CallEntries[] = { {"_cpp11test_sum_int_foreach_", (DL_FUNC) &_cpp11test_sum_int_foreach_, 1}, {"_cpp11test_test_destruction_inner", (DL_FUNC) &_cpp11test_test_destruction_inner, 0}, {"_cpp11test_test_destruction_outer", (DL_FUNC) &_cpp11test_test_destruction_outer, 0}, + {"_cpp11test_unordered_map_to_list_", (DL_FUNC) &_cpp11test_unordered_map_to_list_, 1}, {"_cpp11test_upper_bound", (DL_FUNC) &_cpp11test_upper_bound, 2}, {"run_testthat_tests", (DL_FUNC) &run_testthat_tests, 1}, {NULL, NULL, 0} diff --git a/cpp11test/src/map.cpp b/cpp11test/src/map.cpp new file mode 100644 index 00000000..e4a32db4 --- /dev/null +++ b/cpp11test/src/map.cpp @@ -0,0 +1,20 @@ +#include "cpp11/as.hpp" +#include "cpp11/doubles.hpp" + +[[cpp11::register]] SEXP ordered_map_to_list_(cpp11::doubles x) { + std::map counts; + int n = x.size(); + for (int i = 0; i < n; i++) { + counts[x[i]]++; + } + return cpp11::as_sexp(counts); +} + +[[cpp11::register]] SEXP unordered_map_to_list_(cpp11::doubles x) { + std::unordered_map counts; + int n = x.size(); + for (int i = 0; i < n; i++) { + counts[x[i]]++; + } + return cpp11::as_sexp(counts); +} diff --git a/cpp11test/src/roxygen1.cpp b/cpp11test/src/roxygen1.cpp new file mode 100644 index 00000000..6ce5dea8 --- /dev/null +++ b/cpp11test/src/roxygen1.cpp @@ -0,0 +1,22 @@ +#include "cpp11/doubles.hpp" +using namespace cpp11; + +// Test: not documented + documented + +// Not Roxygenised C++ function I +[[cpp11::register]] double notroxcpp1_(double x) { + double y = x + 1.0; + return y; +} + +/* roxygen start +@title Roxygenise C++ function II +@param x numeric value +@description Dummy function to test roxygen2. It adds 2.0 to a double. +@export +@examples roxcpp2_(1.0) +roxygen end */ +[[cpp11::register]] double roxcpp2_(double x) { + double y = x + 2.0; + return y; +} diff --git a/cpp11test/src/roxygen2.cpp b/cpp11test/src/roxygen2.cpp new file mode 100644 index 00000000..ecd50221 --- /dev/null +++ b/cpp11test/src/roxygen2.cpp @@ -0,0 +1,28 @@ +#include "cpp11/doubles.hpp" +using namespace cpp11; + +// Test: documented + documented + +/* roxygen start +@title Roxygenise C++ function III +@param x numeric value +@description Dummy function to test roxygen2. It adds 3.0 to a double. +@export +@examples roxcpp3_(1.0) +roxygen end */ +[[cpp11::register]] double roxcpp3_(double x) { + double y = x + 3.0; + return y; +} + +/* roxygen start +@title Roxygenise C++ function IV +@param x numeric value +@description Dummy function to test roxygen2. It adds 4.0 to a double. +@export +@examples roxcpp4_(1.0) +roxygen end */ +[[cpp11::register]] double roxcpp4_(double x) { + double y = x + 4.0; + return y; +} diff --git a/cpp11test/src/roxygen3.cpp b/cpp11test/src/roxygen3.cpp new file mode 100644 index 00000000..7ede7a08 --- /dev/null +++ b/cpp11test/src/roxygen3.cpp @@ -0,0 +1,38 @@ +#include "cpp11/doubles.hpp" +using namespace cpp11; + +// Test: documented + not documented + documented + +/* roxygen start +@title Roxygenise C++ function V +@param x numeric value +@description Dummy function to test roxygen2. It adds 5.0 to a double. +@export +@examples roxcpp5_(1.0) +roxygen end */ +[[cpp11::register]] double roxcpp5_(double x) { + double y = x + 5.0; + return y; +} + +// Not Roxygenised C++ function VI +[[cpp11::register]] double notroxcpp6_(double x) { + double y = x + 6.0; + return y; +} + +/* roxygen start +@title Roxygenise C++ function VII +@param x numeric value +@description Dummy function to test roxygen2. It adds 7.0 to a double. +@export +@examples +my_fun <- function(x) { + roxcpp7_(x) +} +@seealso \code{\link{roxcpp1_}} +roxygen end */ +[[cpp11::register]] double roxcpp7_(double x) { + double y = x + 7.0; + return y; +} diff --git a/cpp11test/tests/testthat/test-map-to-list.R b/cpp11test/tests/testthat/test-map-to-list.R new file mode 100644 index 00000000..dc637afa --- /dev/null +++ b/cpp11test/tests/testthat/test-map-to-list.R @@ -0,0 +1,18 @@ +test_that("ordered and unordered C++ maps are converted to R lists", { + set.seed(42L) + x <- rnorm(10L) + xprime <- c(x, x[1]) + + om <- ordered_map_to_list_(x) + expect_type(om, "list") + + om_doubles <- as.double(names(om)) + expect_equal(om_doubles, sort(om_doubles)) + + omprime <- ordered_map_to_list_(xprime) + expect_equal(unlist(unique(omprime)), 1:2) + + um <- unordered_map_to_list_(xprime) + expect_type(um, "list") + expect_equal(unlist(unique(um)), 1:2) +}) diff --git a/inst/include/cpp11/as.hpp b/inst/include/cpp11/as.hpp index 682f12b5..374c0518 100644 --- a/inst/include/cpp11/as.hpp +++ b/inst/include/cpp11/as.hpp @@ -2,10 +2,13 @@ #include // for modf #include // for initializer_list +#include // for std::map #include // for std::shared_ptr, std::weak_ptr, std::unique_ptr #include -#include // for string, basic_string -#include // for decay, enable_if, is_same, is_convertible +#include // for string, basic_string +#include // for decay, enable_if, is_same, is_convertible +#include // for std::unordered_map +#include // for std::vector #include "cpp11/R.hpp" // for SEXP, SEXPREC, Rf_xlength, R_xlen_t #include "cpp11/protect.hpp" // for stop, protect, safe, protect::function @@ -243,7 +246,7 @@ enable_if_integral as_sexp(const Container& from) { } inline SEXP as_sexp(std::initializer_list from) { - return as_sexp>(from); + return as_sexp(std::vector(from)); } template as_sexp(const Container& from) { } inline SEXP as_sexp(std::initializer_list from) { - return as_sexp>(from); + return as_sexp(std::vector(from)); } template as_sexp(const Container& from) { } inline SEXP as_sexp(std::initializer_list from) { - return as_sexp>(from); + return as_sexp(std::vector(from)); } namespace detail { @@ -325,7 +328,7 @@ enable_if_c_string as_sexp(const Container& from) { } inline SEXP as_sexp(std::initializer_list from) { - return as_sexp>(from); + return as_sexp(std::vector(from)); } template > @@ -333,4 +336,73 @@ enable_if_convertible_to_sexp as_sexp(const T& from) { return from; } +// Pacha: Specialization for std::map +// NOTE: I did not use templates to avoid clashes with doubles/function/etc. +inline SEXP as_sexp(const std::map& map) { + R_xlen_t size = map.size(); + SEXP result = PROTECT(Rf_allocVector(VECSXP, size)); + SEXP names = PROTECT(Rf_allocVector(STRSXP, size)); + + auto it = map.begin(); + for (R_xlen_t i = 0; i < size; ++i, ++it) { + SET_VECTOR_ELT(result, i, it->second); + SET_STRING_ELT(names, i, Rf_mkCharCE(it->first.c_str(), CE_UTF8)); + } + + Rf_setAttrib(result, R_NamesSymbol, names); + UNPROTECT(2); + return result; +} + +// Specialization for std::map +inline SEXP as_sexp(const std::map& map) { + R_xlen_t size = map.size(); + SEXP result = PROTECT(Rf_allocVector(VECSXP, size)); + SEXP names = PROTECT(Rf_allocVector(REALSXP, size)); + + auto it = map.begin(); + for (R_xlen_t i = 0; i < size; ++i, ++it) { + SET_VECTOR_ELT(result, i, Rf_ScalarInteger(it->second)); + REAL(names)[i] = it->first; + } + + Rf_setAttrib(result, R_NamesSymbol, names); + UNPROTECT(2); + return result; +} + +// Pacha: Specialization for std::unordered_map +inline SEXP as_sexp(const std::unordered_map& map) { + R_xlen_t size = map.size(); + SEXP result = PROTECT(Rf_allocVector(VECSXP, size)); + SEXP names = PROTECT(Rf_allocVector(STRSXP, size)); + + auto it = map.begin(); + for (R_xlen_t i = 0; i < size; ++i, ++it) { + SET_VECTOR_ELT(result, i, it->second); + SET_STRING_ELT(names, i, Rf_mkCharCE(it->first.c_str(), CE_UTF8)); + } + + Rf_setAttrib(result, R_NamesSymbol, names); + UNPROTECT(2); + return result; +} + +// Specialization for std::unordered_map +inline SEXP as_sexp(const std::unordered_map& map) { + R_xlen_t size = map.size(); + SEXP result = PROTECT(Rf_allocVector(VECSXP, size)); + SEXP names = PROTECT(Rf_allocVector(REALSXP, size)); + + auto it = map.begin(); + for (R_xlen_t i = 0; i < size; ++i, ++it) { + SET_VECTOR_ELT(result, i, Rf_ScalarInteger(it->second)); + REAL(names)[i] = it->first; + } + + Rf_setAttrib(result, R_NamesSymbol, names); + UNPROTECT(2); + return result; +} + } // namespace cpp11 diff --git a/vignettes/cpp11.Rmd b/vignettes/cpp11.Rmd index cabafc1d..89d0701f 100644 --- a/vignettes/cpp11.Rmd +++ b/vignettes/cpp11.Rmd @@ -878,8 +878,6 @@ logicals duplicated_cpp(integers x) { } ``` -````{=html} - -```` ### Exercises