Skip to content

Commit 686ae04

Browse files
committed
Get findIntervals example working
The iterators needed to support copy assignment, and I also implemented part of a RandomAccessIterator so upper_bound was more efficient
1 parent ecbe0a3 commit 686ae04

File tree

10 files changed

+249
-51
lines changed

10 files changed

+249
-51
lines changed

cpp11test/R/cpp11-exports.R

+26-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,30 @@ data_frame_ <- function(){
88
.Call("_cpp11test_data_frame_" )
99
}
1010

11+
remove_altrep <- function(x){
12+
.Call("_cpp11test_remove_altrep" , x)
13+
}
14+
15+
upper_bound <- function(x, breaks){
16+
.Call("_cpp11test_upper_bound" , x, breaks)
17+
}
18+
19+
findInterval2 <- function(x, breaks){
20+
.Call("_cpp11test_findInterval2" , x, breaks)
21+
}
22+
23+
findInterval2_5 <- function(x, breaks){
24+
.Call("_cpp11test_findInterval2_5" , x, breaks)
25+
}
26+
27+
findInterval3 <- function(x, breaks){
28+
.Call("_cpp11test_findInterval3" , x, breaks)
29+
}
30+
31+
findInterval4 <- function(x, breaks){
32+
.Call("_cpp11test_findInterval4" , x, breaks)
33+
}
34+
1135
grow_ <- function(n){
1236
.Call("_cpp11test_grow_" , n)
1337
}
@@ -33,11 +57,11 @@ gibbs_rcpp2 <- function(N, thin){
3357
}
3458

3559
cpp11_release_ <- function(n){
36-
invisible(.Call("_cpp11test_cpp11_release_" , n))
60+
invisible(.Call("_cpp11test_cpp11_release_", PACKAGE = "cpp11test" , n))
3761
}
3862

3963
rcpp_release_ <- function(n){
40-
invisible(.Call("_cpp11test_rcpp_release_" , n))
64+
invisible(.Call("_cpp11test_rcpp_release_", PACKAGE = "cpp11test" , n))
4165
}
4266

4367
cpp11_safe_ <- function(x_sxp){

cpp11test/src/cpp11-exports.cpp

+54
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,48 @@ extern "C" SEXP _cpp11test_data_frame_() {
1818
return cpp11::as_sexp(data_frame_());
1919
END_CPP11
2020
}
21+
// find-intervals.cpp
22+
SEXP remove_altrep(SEXP x);
23+
extern "C" SEXP _cpp11test_remove_altrep(SEXP x) {
24+
BEGIN_CPP11
25+
return cpp11::as_sexp(remove_altrep(cpp11::unmove(cpp11::as_cpp<SEXP>(x))));
26+
END_CPP11
27+
}
28+
// find-intervals.cpp
29+
double upper_bound(doubles x, doubles breaks);
30+
extern "C" SEXP _cpp11test_upper_bound(SEXP x, SEXP breaks) {
31+
BEGIN_CPP11
32+
return cpp11::as_sexp(upper_bound(cpp11::unmove(cpp11::as_cpp<doubles>(x)), cpp11::unmove(cpp11::as_cpp<doubles>(breaks))));
33+
END_CPP11
34+
}
35+
// find-intervals.cpp
36+
integers findInterval2(doubles x, doubles breaks);
37+
extern "C" SEXP _cpp11test_findInterval2(SEXP x, SEXP breaks) {
38+
BEGIN_CPP11
39+
return cpp11::as_sexp(findInterval2(cpp11::unmove(cpp11::as_cpp<doubles>(x)), cpp11::unmove(cpp11::as_cpp<doubles>(breaks))));
40+
END_CPP11
41+
}
42+
// find-intervals.cpp
43+
integers findInterval2_5(doubles x, doubles breaks);
44+
extern "C" SEXP _cpp11test_findInterval2_5(SEXP x, SEXP breaks) {
45+
BEGIN_CPP11
46+
return cpp11::as_sexp(findInterval2_5(cpp11::unmove(cpp11::as_cpp<doubles>(x)), cpp11::unmove(cpp11::as_cpp<doubles>(breaks))));
47+
END_CPP11
48+
}
49+
// find-intervals.cpp
50+
integers findInterval3(doubles x, doubles breaks);
51+
extern "C" SEXP _cpp11test_findInterval3(SEXP x, SEXP breaks) {
52+
BEGIN_CPP11
53+
return cpp11::as_sexp(findInterval3(cpp11::unmove(cpp11::as_cpp<doubles>(x)), cpp11::unmove(cpp11::as_cpp<doubles>(breaks))));
54+
END_CPP11
55+
}
56+
// find-intervals.cpp
57+
IntegerVector findInterval4(NumericVector x, NumericVector breaks);
58+
extern "C" SEXP _cpp11test_findInterval4(SEXP x, SEXP breaks) {
59+
BEGIN_CPP11
60+
return cpp11::as_sexp(findInterval4(cpp11::unmove(cpp11::as_cpp<NumericVector>(x)), cpp11::unmove(cpp11::as_cpp<NumericVector>(breaks))));
61+
END_CPP11
62+
}
2163
// grow.cpp
2264
cpp11::writable::doubles grow_(R_xlen_t n);
2365
extern "C" SEXP _cpp11test_grow_(SEXP n) {
@@ -175,6 +217,10 @@ extern SEXP _cpp11test_cpp11_insert_(SEXP);
175217
extern SEXP _cpp11test_cpp11_release_(SEXP);
176218
extern SEXP _cpp11test_cpp11_safe_(SEXP);
177219
extern SEXP _cpp11test_data_frame_();
220+
extern SEXP _cpp11test_findInterval2(SEXP, SEXP);
221+
extern SEXP _cpp11test_findInterval2_5(SEXP, SEXP);
222+
extern SEXP _cpp11test_findInterval3(SEXP, SEXP);
223+
extern SEXP _cpp11test_findInterval4(SEXP, SEXP);
178224
extern SEXP _cpp11test_gibbs_cpp(SEXP, SEXP);
179225
extern SEXP _cpp11test_gibbs_cpp2(SEXP, SEXP);
180226
extern SEXP _cpp11test_gibbs_rcpp(SEXP, SEXP);
@@ -185,6 +231,7 @@ extern SEXP _cpp11test_rcpp_release_(SEXP);
185231
extern SEXP _cpp11test_rcpp_sum_dbl_accumulate_(SEXP);
186232
extern SEXP _cpp11test_rcpp_sum_dbl_for_(SEXP);
187233
extern SEXP _cpp11test_rcpp_sum_dbl_foreach_(SEXP);
234+
extern SEXP _cpp11test_remove_altrep(SEXP);
188235
extern SEXP _cpp11test_sum_dbl_accumulate_(SEXP);
189236
extern SEXP _cpp11test_sum_dbl_accumulate2_(SEXP);
190237
extern SEXP _cpp11test_sum_dbl_for_(SEXP);
@@ -193,6 +240,7 @@ extern SEXP _cpp11test_sum_dbl_for3_(SEXP);
193240
extern SEXP _cpp11test_sum_dbl_foreach_(SEXP);
194241
extern SEXP _cpp11test_sum_dbl_foreach2_(SEXP);
195242
extern SEXP _cpp11test_sum_int_for_(SEXP);
243+
extern SEXP _cpp11test_upper_bound(SEXP, SEXP);
196244
extern SEXP run_testthat_tests(SEXP);
197245

198246
static const R_CallMethodDef CallEntries[] = {
@@ -201,6 +249,10 @@ static const R_CallMethodDef CallEntries[] = {
201249
{"_cpp11test_cpp11_release_", (DL_FUNC) &_cpp11test_cpp11_release_, 1},
202250
{"_cpp11test_cpp11_safe_", (DL_FUNC) &_cpp11test_cpp11_safe_, 1},
203251
{"_cpp11test_data_frame_", (DL_FUNC) &_cpp11test_data_frame_, 0},
252+
{"_cpp11test_findInterval2", (DL_FUNC) &_cpp11test_findInterval2, 2},
253+
{"_cpp11test_findInterval2_5", (DL_FUNC) &_cpp11test_findInterval2_5, 2},
254+
{"_cpp11test_findInterval3", (DL_FUNC) &_cpp11test_findInterval3, 2},
255+
{"_cpp11test_findInterval4", (DL_FUNC) &_cpp11test_findInterval4, 2},
204256
{"_cpp11test_gibbs_cpp", (DL_FUNC) &_cpp11test_gibbs_cpp, 2},
205257
{"_cpp11test_gibbs_cpp2", (DL_FUNC) &_cpp11test_gibbs_cpp2, 2},
206258
{"_cpp11test_gibbs_rcpp", (DL_FUNC) &_cpp11test_gibbs_rcpp, 2},
@@ -211,6 +263,7 @@ static const R_CallMethodDef CallEntries[] = {
211263
{"_cpp11test_rcpp_sum_dbl_accumulate_", (DL_FUNC) &_cpp11test_rcpp_sum_dbl_accumulate_, 1},
212264
{"_cpp11test_rcpp_sum_dbl_for_", (DL_FUNC) &_cpp11test_rcpp_sum_dbl_for_, 1},
213265
{"_cpp11test_rcpp_sum_dbl_foreach_", (DL_FUNC) &_cpp11test_rcpp_sum_dbl_foreach_, 1},
266+
{"_cpp11test_remove_altrep", (DL_FUNC) &_cpp11test_remove_altrep, 1},
214267
{"_cpp11test_sum_dbl_accumulate_", (DL_FUNC) &_cpp11test_sum_dbl_accumulate_, 1},
215268
{"_cpp11test_sum_dbl_accumulate2_", (DL_FUNC) &_cpp11test_sum_dbl_accumulate2_, 1},
216269
{"_cpp11test_sum_dbl_for_", (DL_FUNC) &_cpp11test_sum_dbl_for_, 1},
@@ -219,6 +272,7 @@ static const R_CallMethodDef CallEntries[] = {
219272
{"_cpp11test_sum_dbl_foreach_", (DL_FUNC) &_cpp11test_sum_dbl_foreach_, 1},
220273
{"_cpp11test_sum_dbl_foreach2_", (DL_FUNC) &_cpp11test_sum_dbl_foreach2_, 1},
221274
{"_cpp11test_sum_int_for_", (DL_FUNC) &_cpp11test_sum_int_for_, 1},
275+
{"_cpp11test_upper_bound", (DL_FUNC) &_cpp11test_upper_bound, 2},
222276
{"run_testthat_tests", (DL_FUNC) &run_testthat_tests, 1},
223277
{NULL, NULL, 0}
224278
};

cpp11test/src/find-intervals.cpp

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include <algorithm>
2+
#include "cpp11.hpp"
3+
using namespace cpp11;
4+
5+
#include <Rcpp.h>
6+
#include <algorithm>
7+
using namespace Rcpp;
8+
9+
[[cpp11::export]] SEXP remove_altrep(SEXP x) {
10+
SEXP out = PROTECT(Rf_allocVector(REALSXP, Rf_xlength(x)));
11+
memcpy(REAL(out), REAL(x), Rf_xlength(x));
12+
13+
UNPROTECT(1);
14+
return out;
15+
}
16+
17+
[[cpp11::export]] double upper_bound(doubles x, doubles breaks) {
18+
auto pos = std::upper_bound(breaks.begin(), breaks.end(), x[0]);
19+
return std::distance(breaks.begin(), pos);
20+
}
21+
22+
[[cpp11::export]] integers findInterval2(doubles x, doubles breaks) {
23+
writable::integers out(x.size());
24+
auto out_it = out.begin();
25+
26+
for (auto&& val : x) {
27+
auto pos = std::upper_bound(breaks.begin(), breaks.end(), val);
28+
*out_it = std::distance(breaks.begin(), pos);
29+
++out_it;
30+
}
31+
return out;
32+
}
33+
[[cpp11::export]] integers findInterval2_5(doubles x, doubles breaks) {
34+
writable::integers out(x.size());
35+
auto out_it = out.begin();
36+
auto bb = breaks.begin();
37+
auto be = breaks.end();
38+
39+
for (auto&& val : x) {
40+
auto pos = std::upper_bound(bb, be, val);
41+
*out_it = std::distance(bb, pos);
42+
++out_it;
43+
}
44+
return out;
45+
}
46+
47+
// This version avoids the overhead of the cpp11 iterator types
48+
[[cpp11::export]] integers findInterval3(doubles x, doubles breaks) {
49+
writable::integers out(x.size());
50+
auto out_it = out.begin();
51+
auto b = REAL(breaks);
52+
auto e = REAL(breaks) + Rf_xlength(breaks);
53+
double* pos;
54+
55+
for (auto&& val : x) {
56+
pos = std::upper_bound(b, e, val);
57+
*out_it = std::distance(b, pos);
58+
++out_it;
59+
}
60+
return out;
61+
}
62+
63+
[[cpp11::export]] IntegerVector findInterval4(NumericVector x, NumericVector breaks) {
64+
IntegerVector out(x.size());
65+
66+
NumericVector::iterator it, it_end, pos, b, e;
67+
IntegerVector::iterator out_it;
68+
it_end = x.end();
69+
b = breaks.begin();
70+
e = breaks.end();
71+
72+
for (it = x.begin(), out_it = out.begin(); it != it_end; ++it, ++out_it) {
73+
pos = std::upper_bound(b, e, *it);
74+
*out_it = std::distance(b, pos);
75+
}
76+
77+
return out;
78+
}

inst/include/cpp11/doubles.hpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#pragma once
22

3-
#include <algorithm> // for min
4-
#include <array> // for array
5-
#include <initializer_list> // for initializer_list
6-
#include <stdexcept> // for out_of_range
3+
#include <algorithm> // for min
4+
#include <array> // for array
5+
#include <initializer_list> // for initializer_list
6+
#include <stdexcept> // for out_of_range
77
#include "cpp11/as.hpp" // for as_sexp
88
#include "cpp11/named_arg.hpp" // for named_arg
99
#include "cpp11/protect.hpp" // for SEXP, SEXPREC, REAL_ELT, R_Preserve...
@@ -46,8 +46,8 @@ inline double* vector<double>::get_p(bool is_altrep, SEXP data) {
4646

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

inst/include/cpp11/integers.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ inline int* vector<int>::get_p(bool is_altrep, SEXP data) {
4747

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

inst/include/cpp11/logicals.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ inline Rboolean* vector<Rboolean>::get_p(bool is_altrep, SEXP data) {
4545

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

inst/include/cpp11/raws.hpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#pragma once
22

3-
#include <algorithm> // for min
4-
#include <array> // for array
5-
#include <cstdint> // for uint8_t
6-
#include <initializer_list> // for initializer_list
7-
#include <stdexcept> // for out_of_range
3+
#include <algorithm> // for min
4+
#include <array> // for array
5+
#include <cstdint> // for uint8_t
6+
#include <initializer_list> // for initializer_list
7+
#include <stdexcept> // for out_of_range
88
#include "cpp11/R.hpp" // for RAW, protect_sexp, SEXP, SEXPREC
99
#include "cpp11/named_arg.hpp" // for named_arg
1010
#include "cpp11/protect.hpp" // for unwind_protect, protect, protect::f...
@@ -48,9 +48,9 @@ inline uint8_t* vector<uint8_t>::get_p(bool is_altrep, SEXP data) {
4848

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

inst/include/cpp11/strings.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ inline void vector<string>::const_iterator::fill_buf(R_xlen_t) {
4949

5050
template <>
5151
inline string vector<string>::const_iterator::operator*() {
52-
return STRING_ELT(data_.data(), pos_);
52+
return STRING_ELT(data_->data(), pos_);
5353
}
5454

5555
typedef vector<string> strings;

0 commit comments

Comments
 (0)