Skip to content

Commit

Permalink
Get findIntervals example working
Browse files Browse the repository at this point in the history
The iterators needed to support copy assignment, and I also implemented
part of a RandomAccessIterator so upper_bound was more efficient
  • Loading branch information
jimhester committed Jun 18, 2020
1 parent ecbe0a3 commit 686ae04
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 51 deletions.
28 changes: 26 additions & 2 deletions cpp11test/R/cpp11-exports.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,30 @@ data_frame_ <- function(){
.Call("_cpp11test_data_frame_" )
}

remove_altrep <- function(x){
.Call("_cpp11test_remove_altrep" , x)
}

upper_bound <- function(x, breaks){
.Call("_cpp11test_upper_bound" , x, breaks)
}

findInterval2 <- function(x, breaks){
.Call("_cpp11test_findInterval2" , x, breaks)
}

findInterval2_5 <- function(x, breaks){
.Call("_cpp11test_findInterval2_5" , x, breaks)
}

findInterval3 <- function(x, breaks){
.Call("_cpp11test_findInterval3" , x, breaks)
}

findInterval4 <- function(x, breaks){
.Call("_cpp11test_findInterval4" , x, breaks)
}

grow_ <- function(n){
.Call("_cpp11test_grow_" , n)
}
Expand All @@ -33,11 +57,11 @@ gibbs_rcpp2 <- function(N, thin){
}

cpp11_release_ <- function(n){
invisible(.Call("_cpp11test_cpp11_release_" , n))
invisible(.Call("_cpp11test_cpp11_release_", PACKAGE = "cpp11test" , n))
}

rcpp_release_ <- function(n){
invisible(.Call("_cpp11test_rcpp_release_" , n))
invisible(.Call("_cpp11test_rcpp_release_", PACKAGE = "cpp11test" , n))
}

cpp11_safe_ <- function(x_sxp){
Expand Down
54 changes: 54 additions & 0 deletions cpp11test/src/cpp11-exports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,48 @@ extern "C" SEXP _cpp11test_data_frame_() {
return cpp11::as_sexp(data_frame_());
END_CPP11
}
// find-intervals.cpp
SEXP remove_altrep(SEXP x);
extern "C" SEXP _cpp11test_remove_altrep(SEXP x) {
BEGIN_CPP11
return cpp11::as_sexp(remove_altrep(cpp11::unmove(cpp11::as_cpp<SEXP>(x))));
END_CPP11
}
// find-intervals.cpp
double upper_bound(doubles x, doubles breaks);
extern "C" SEXP _cpp11test_upper_bound(SEXP x, SEXP breaks) {
BEGIN_CPP11
return cpp11::as_sexp(upper_bound(cpp11::unmove(cpp11::as_cpp<doubles>(x)), cpp11::unmove(cpp11::as_cpp<doubles>(breaks))));
END_CPP11
}
// find-intervals.cpp
integers findInterval2(doubles x, doubles breaks);
extern "C" SEXP _cpp11test_findInterval2(SEXP x, SEXP breaks) {
BEGIN_CPP11
return cpp11::as_sexp(findInterval2(cpp11::unmove(cpp11::as_cpp<doubles>(x)), cpp11::unmove(cpp11::as_cpp<doubles>(breaks))));
END_CPP11
}
// find-intervals.cpp
integers findInterval2_5(doubles x, doubles breaks);
extern "C" SEXP _cpp11test_findInterval2_5(SEXP x, SEXP breaks) {
BEGIN_CPP11
return cpp11::as_sexp(findInterval2_5(cpp11::unmove(cpp11::as_cpp<doubles>(x)), cpp11::unmove(cpp11::as_cpp<doubles>(breaks))));
END_CPP11
}
// find-intervals.cpp
integers findInterval3(doubles x, doubles breaks);
extern "C" SEXP _cpp11test_findInterval3(SEXP x, SEXP breaks) {
BEGIN_CPP11
return cpp11::as_sexp(findInterval3(cpp11::unmove(cpp11::as_cpp<doubles>(x)), cpp11::unmove(cpp11::as_cpp<doubles>(breaks))));
END_CPP11
}
// find-intervals.cpp
IntegerVector findInterval4(NumericVector x, NumericVector breaks);
extern "C" SEXP _cpp11test_findInterval4(SEXP x, SEXP breaks) {
BEGIN_CPP11
return cpp11::as_sexp(findInterval4(cpp11::unmove(cpp11::as_cpp<NumericVector>(x)), cpp11::unmove(cpp11::as_cpp<NumericVector>(breaks))));
END_CPP11
}
// grow.cpp
cpp11::writable::doubles grow_(R_xlen_t n);
extern "C" SEXP _cpp11test_grow_(SEXP n) {
Expand Down Expand Up @@ -175,6 +217,10 @@ extern SEXP _cpp11test_cpp11_insert_(SEXP);
extern SEXP _cpp11test_cpp11_release_(SEXP);
extern SEXP _cpp11test_cpp11_safe_(SEXP);
extern SEXP _cpp11test_data_frame_();
extern SEXP _cpp11test_findInterval2(SEXP, SEXP);
extern SEXP _cpp11test_findInterval2_5(SEXP, SEXP);
extern SEXP _cpp11test_findInterval3(SEXP, SEXP);
extern SEXP _cpp11test_findInterval4(SEXP, SEXP);
extern SEXP _cpp11test_gibbs_cpp(SEXP, SEXP);
extern SEXP _cpp11test_gibbs_cpp2(SEXP, SEXP);
extern SEXP _cpp11test_gibbs_rcpp(SEXP, SEXP);
Expand All @@ -185,6 +231,7 @@ extern SEXP _cpp11test_rcpp_release_(SEXP);
extern SEXP _cpp11test_rcpp_sum_dbl_accumulate_(SEXP);
extern SEXP _cpp11test_rcpp_sum_dbl_for_(SEXP);
extern SEXP _cpp11test_rcpp_sum_dbl_foreach_(SEXP);
extern SEXP _cpp11test_remove_altrep(SEXP);
extern SEXP _cpp11test_sum_dbl_accumulate_(SEXP);
extern SEXP _cpp11test_sum_dbl_accumulate2_(SEXP);
extern SEXP _cpp11test_sum_dbl_for_(SEXP);
Expand All @@ -193,6 +240,7 @@ extern SEXP _cpp11test_sum_dbl_for3_(SEXP);
extern SEXP _cpp11test_sum_dbl_foreach_(SEXP);
extern SEXP _cpp11test_sum_dbl_foreach2_(SEXP);
extern SEXP _cpp11test_sum_int_for_(SEXP);
extern SEXP _cpp11test_upper_bound(SEXP, SEXP);
extern SEXP run_testthat_tests(SEXP);

static const R_CallMethodDef CallEntries[] = {
Expand All @@ -201,6 +249,10 @@ static const R_CallMethodDef CallEntries[] = {
{"_cpp11test_cpp11_release_", (DL_FUNC) &_cpp11test_cpp11_release_, 1},
{"_cpp11test_cpp11_safe_", (DL_FUNC) &_cpp11test_cpp11_safe_, 1},
{"_cpp11test_data_frame_", (DL_FUNC) &_cpp11test_data_frame_, 0},
{"_cpp11test_findInterval2", (DL_FUNC) &_cpp11test_findInterval2, 2},
{"_cpp11test_findInterval2_5", (DL_FUNC) &_cpp11test_findInterval2_5, 2},
{"_cpp11test_findInterval3", (DL_FUNC) &_cpp11test_findInterval3, 2},
{"_cpp11test_findInterval4", (DL_FUNC) &_cpp11test_findInterval4, 2},
{"_cpp11test_gibbs_cpp", (DL_FUNC) &_cpp11test_gibbs_cpp, 2},
{"_cpp11test_gibbs_cpp2", (DL_FUNC) &_cpp11test_gibbs_cpp2, 2},
{"_cpp11test_gibbs_rcpp", (DL_FUNC) &_cpp11test_gibbs_rcpp, 2},
Expand All @@ -211,6 +263,7 @@ static const R_CallMethodDef CallEntries[] = {
{"_cpp11test_rcpp_sum_dbl_accumulate_", (DL_FUNC) &_cpp11test_rcpp_sum_dbl_accumulate_, 1},
{"_cpp11test_rcpp_sum_dbl_for_", (DL_FUNC) &_cpp11test_rcpp_sum_dbl_for_, 1},
{"_cpp11test_rcpp_sum_dbl_foreach_", (DL_FUNC) &_cpp11test_rcpp_sum_dbl_foreach_, 1},
{"_cpp11test_remove_altrep", (DL_FUNC) &_cpp11test_remove_altrep, 1},
{"_cpp11test_sum_dbl_accumulate_", (DL_FUNC) &_cpp11test_sum_dbl_accumulate_, 1},
{"_cpp11test_sum_dbl_accumulate2_", (DL_FUNC) &_cpp11test_sum_dbl_accumulate2_, 1},
{"_cpp11test_sum_dbl_for_", (DL_FUNC) &_cpp11test_sum_dbl_for_, 1},
Expand All @@ -219,6 +272,7 @@ static const R_CallMethodDef CallEntries[] = {
{"_cpp11test_sum_dbl_foreach_", (DL_FUNC) &_cpp11test_sum_dbl_foreach_, 1},
{"_cpp11test_sum_dbl_foreach2_", (DL_FUNC) &_cpp11test_sum_dbl_foreach2_, 1},
{"_cpp11test_sum_int_for_", (DL_FUNC) &_cpp11test_sum_int_for_, 1},
{"_cpp11test_upper_bound", (DL_FUNC) &_cpp11test_upper_bound, 2},
{"run_testthat_tests", (DL_FUNC) &run_testthat_tests, 1},
{NULL, NULL, 0}
};
Expand Down
78 changes: 78 additions & 0 deletions cpp11test/src/find-intervals.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include <algorithm>
#include "cpp11.hpp"
using namespace cpp11;

#include <Rcpp.h>
#include <algorithm>
using namespace Rcpp;

[[cpp11::export]] SEXP remove_altrep(SEXP x) {
SEXP out = PROTECT(Rf_allocVector(REALSXP, Rf_xlength(x)));
memcpy(REAL(out), REAL(x), Rf_xlength(x));

UNPROTECT(1);
return out;
}

[[cpp11::export]] double upper_bound(doubles x, doubles breaks) {
auto pos = std::upper_bound(breaks.begin(), breaks.end(), x[0]);
return std::distance(breaks.begin(), pos);
}

[[cpp11::export]] integers findInterval2(doubles x, doubles breaks) {
writable::integers out(x.size());
auto out_it = out.begin();

for (auto&& val : x) {
auto pos = std::upper_bound(breaks.begin(), breaks.end(), val);
*out_it = std::distance(breaks.begin(), pos);
++out_it;
}
return out;
}
[[cpp11::export]] integers findInterval2_5(doubles x, doubles breaks) {
writable::integers out(x.size());
auto out_it = out.begin();
auto bb = breaks.begin();
auto be = breaks.end();

for (auto&& val : x) {
auto pos = std::upper_bound(bb, be, val);
*out_it = std::distance(bb, pos);
++out_it;
}
return out;
}

// This version avoids the overhead of the cpp11 iterator types
[[cpp11::export]] integers findInterval3(doubles x, doubles breaks) {
writable::integers out(x.size());
auto out_it = out.begin();
auto b = REAL(breaks);
auto e = REAL(breaks) + Rf_xlength(breaks);
double* pos;

for (auto&& val : x) {
pos = std::upper_bound(b, e, val);
*out_it = std::distance(b, pos);
++out_it;
}
return out;
}

[[cpp11::export]] IntegerVector findInterval4(NumericVector x, NumericVector breaks) {
IntegerVector out(x.size());

NumericVector::iterator it, it_end, pos, b, e;
IntegerVector::iterator out_it;
it_end = x.end();
b = breaks.begin();
e = breaks.end();

for (it = x.begin(), out_it = out.begin(); it != it_end; ++it, ++out_it) {
pos = std::upper_bound(b, e, *it);
*out_it = std::distance(b, pos);
}

return out;
}
12 changes: 6 additions & 6 deletions inst/include/cpp11/doubles.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#pragma once

#include <algorithm> // for min
#include <array> // for array
#include <initializer_list> // for initializer_list
#include <stdexcept> // for out_of_range
#include <algorithm> // for min
#include <array> // for array
#include <initializer_list> // for initializer_list
#include <stdexcept> // for out_of_range
#include "cpp11/as.hpp" // for as_sexp
#include "cpp11/named_arg.hpp" // for named_arg
#include "cpp11/protect.hpp" // for SEXP, SEXPREC, REAL_ELT, R_Preserve...
Expand Down Expand Up @@ -46,8 +46,8 @@ inline double* vector<double>::get_p(bool is_altrep, SEXP data) {

template <>
inline void vector<double>::const_iterator::fill_buf(R_xlen_t pos) {
length_ = std::min(static_cast<R_xlen_t>(64L), data_.size() - pos);
unwind_protect([&] { REAL_GET_REGION(data_.data_, pos, length_, buf_.data()); });
length_ = std::min(static_cast<R_xlen_t>(64L), data_->size() - pos);
REAL_GET_REGION(data_->data_, pos, length_, buf_.data());
block_start_ = pos;
}

Expand Down
4 changes: 2 additions & 2 deletions inst/include/cpp11/integers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ inline int* vector<int>::get_p(bool is_altrep, SEXP data) {

template <>
inline void vector<int>::const_iterator::fill_buf(R_xlen_t pos) {
length_ = std::min(static_cast<R_xlen_t>(64L), data_.size() - pos);
unwind_protect([&] { INTEGER_GET_REGION(data_.data_, pos, length_, buf_.data()); });
length_ = std::min(static_cast<R_xlen_t>(64L), data_->size() - pos);
unwind_protect([&] { INTEGER_GET_REGION(data_->data_, pos, length_, buf_.data()); });
block_start_ = pos;
}

Expand Down
4 changes: 2 additions & 2 deletions inst/include/cpp11/logicals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ inline Rboolean* vector<Rboolean>::get_p(bool is_altrep, SEXP data) {

template <>
inline void vector<Rboolean>::const_iterator::fill_buf(R_xlen_t pos) {
length_ = std::min(static_cast<R_xlen_t>(64L), data_.size() - pos);
LOGICAL_GET_REGION(data_.data_, pos, length_, reinterpret_cast<int*>(buf_.data()));
length_ = std::min(static_cast<R_xlen_t>(64L), data_->size() - pos);
LOGICAL_GET_REGION(data_->data_, pos, length_, reinterpret_cast<int*>(buf_.data()));
block_start_ = pos;
}

Expand Down
14 changes: 7 additions & 7 deletions inst/include/cpp11/raws.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#pragma once

#include <algorithm> // for min
#include <array> // for array
#include <cstdint> // for uint8_t
#include <initializer_list> // for initializer_list
#include <stdexcept> // for out_of_range
#include <algorithm> // for min
#include <array> // for array
#include <cstdint> // for uint8_t
#include <initializer_list> // for initializer_list
#include <stdexcept> // for out_of_range
#include "cpp11/R.hpp" // for RAW, protect_sexp, SEXP, SEXPREC
#include "cpp11/named_arg.hpp" // for named_arg
#include "cpp11/protect.hpp" // for unwind_protect, protect, protect::f...
Expand Down Expand Up @@ -48,9 +48,9 @@ inline uint8_t* vector<uint8_t>::get_p(bool is_altrep, SEXP data) {

template <>
inline void vector<uint8_t>::const_iterator::fill_buf(R_xlen_t pos) {
length_ = std::min(static_cast<R_xlen_t>(64L), data_.size() - pos);
length_ = std::min(static_cast<R_xlen_t>(64L), data_->size() - pos);
unwind_protect(
[&] { RAW_GET_REGION(data_.data_, pos, length_, (uint8_t*)buf_.data()); });
[&] { RAW_GET_REGION(data_->data_, pos, length_, (uint8_t*)buf_.data()); });
block_start_ = pos;
}

Expand Down
2 changes: 1 addition & 1 deletion inst/include/cpp11/strings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ inline void vector<string>::const_iterator::fill_buf(R_xlen_t) {

template <>
inline string vector<string>::const_iterator::operator*() {
return STRING_ELT(data_.data(), pos_);
return STRING_ELT(data_->data(), pos_);
}

typedef vector<string> strings;
Expand Down
Loading

0 comments on commit 686ae04

Please sign in to comment.