Skip to content

Commit 32b70a4

Browse files
committed
route range-to-range assignment through the aliasing checks
Also mark Range as elementwise, include sugar_operand.h from is_elementwise.h, and drop stale FIXME comments in ifelse.h.
1 parent e03c2ed commit 32b70a4

6 files changed

Lines changed: 42 additions & 8 deletions

File tree

‎inst/include/Rcpp/sugar/Range.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ namespace Rcpp{
2727

2828
class Range : public VectorBase<INTSXP,false, Range >{
2929
public:
30+
typedef traits::elementwise_operands<> rcpp_elementwise ;
31+
3032
Range( R_xlen_t start_, R_xlen_t end__ ) : start(start_), end_(end__){
3133
if( start_ > end__ ){
3234
throw std::range_error( "upper value must be greater than lower value" ) ;

‎inst/include/Rcpp/sugar/functions/ifelse.h‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,7 @@ class IfElse_Primitive_Primitive : public VectorBase<
287287
typedef Rcpp::traits::elementwise_operands< COND_TYPE > rcpp_elementwise ;
288288

289289
IfElse_Primitive_Primitive( const COND_TYPE& cond_, STORAGE lhs_, STORAGE rhs_ ) :
290-
cond(cond_.get_ref()), lhs(lhs_), rhs(rhs_) {
291-
/* FIXME : cond, lhs and rhs must all have the same size */
292-
}
290+
cond(cond_.get_ref()), lhs(lhs_), rhs(rhs_) {}
293291

294292
inline STORAGE operator[]( R_xlen_t i ) const {
295293
int x = cond[i] ;
@@ -321,9 +319,7 @@ class IfElse_Primitive_Primitive<RTYPE,false,COND_T> : public VectorBase<
321319
typedef Rcpp::traits::elementwise_operands< COND_TYPE > rcpp_elementwise ;
322320

323321
IfElse_Primitive_Primitive( const COND_TYPE& cond_, STORAGE lhs_, STORAGE rhs_ ) :
324-
cond(cond_.get_ref()), lhs(lhs_), rhs(rhs_) {
325-
/* FIXME : cond, lhs and rhs must all have the same size */
326-
}
322+
cond(cond_.get_ref()), lhs(lhs_), rhs(rhs_) {}
327323

328324
inline STORAGE operator[]( R_xlen_t i ) const {
329325
return cond[i] ? lhs : rhs ;

‎inst/include/Rcpp/traits/is_elementwise.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#ifndef Rcpp__traits__is_elementwise_h
2424
#define Rcpp__traits__is_elementwise_h
2525

26+
#include <Rcpp/traits/sugar_operand.h>
27+
2628
namespace Rcpp{
2729
namespace traits{
2830

‎inst/include/Rcpp/vector/RangeIndexer.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,20 @@ class RangeIndexer : public VectorBase<RTYPE, NA, RangeIndexer<RTYPE,NA,VECTOR>
6767
RangeIndexer( VECTOR& vec_, const Rcpp::Range& range_) :
6868
start(vec_.begin() + range_.get_start() ), size_( range_.size() ) {}
6969

70+
RangeIndexer( const RangeIndexer& other ) :
71+
start(other.start), size_(other.size_) {}
72+
7073
template <bool NA_, typename T>
7174
RangeIndexer& operator=( const Rcpp::VectorBase<RTYPE,NA_,T>& x){
7275
UNROLL_LOOP(=)
7376
}
7477

78+
// without this, assigning one range to another would use the implicit
79+
// copy assignment, which rebinds this range instead of copying elements
80+
RangeIndexer& operator=( const RangeIndexer& x ){
81+
return operator=( static_cast<const Rcpp::VectorBase<RTYPE,NA,RangeIndexer>&>(x) ) ;
82+
}
83+
7584
template <bool NA_, typename T>
7685
RangeIndexer& operator+=( const Rcpp::VectorBase<RTYPE,NA_,T>& x){
7786
UNROLL_LOOP(+=)

‎inst/tinytest/cpp/sugar_expressions.cpp‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,20 @@ NumericVector alias_range_shift(NumericVector x) {
149149
return x;
150150
}
151151

152+
// [[Rcpp::export]]
153+
NumericVector alias_range_range(NumericVector x) {
154+
R_xlen_t n = x.size();
155+
x[Range(1, n - 1)] = x[Range(0, n - 2)];
156+
return x;
157+
}
158+
159+
// [[Rcpp::export]]
160+
NumericVector alias_range_range_add(NumericVector x) {
161+
R_xlen_t n = x.size();
162+
x[Range(1, n - 1)] += x[Range(0, n - 2)];
163+
return x;
164+
}
165+
152166
// [[Rcpp::export]]
153167
NumericVector alias_range_rev(NumericVector x) {
154168
R_xlen_t n = x.size();
@@ -223,6 +237,7 @@ LogicalVector elementwise_flags(NumericVector x, NumericMatrix m) {
223237
bool row_row = traits::is_elementwise<decltype(m(0, _) + 1.0), RT>::value;
224238
bool row_column = traits::is_elementwise<decltype(m(0, _) + 1.0), CT>::value;
225239
bool range_range = traits::is_elementwise<decltype(x[Range(0, 1)] + 1.0), GT>::value;
240+
bool sequence = traits::is_elementwise<decltype(seq(0, 1)), GT>::value;
226241

227242
return LogicalVector::create(
228243
_["vector"] = vector,
@@ -237,7 +252,8 @@ LogicalVector elementwise_flags(NumericVector x, NumericMatrix m) {
237252
_["column_row"] = column_row,
238253
_["row_row"] = row_row,
239254
_["row_column"] = row_column,
240-
_["range_range"] = range_range
255+
_["range_range"] = range_range,
256+
_["seq"] = sequence
241257
);
242258
}
243259

@@ -277,6 +293,12 @@ NumericVector length_range(NumericVector x, NumericVector y) {
277293
return x;
278294
}
279295

296+
// [[Rcpp::export]]
297+
NumericVector length_range_range(NumericVector x) {
298+
x[Range(0, 1)] = x[Range(0, 3)];
299+
return x;
300+
}
301+
280302
// [[Rcpp::export]]
281303
NumericMatrix length_column(NumericMatrix m, NumericVector y) {
282304
m(_, 0) = y;

‎inst/tinytest/test_sugar.R‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1734,6 +1734,8 @@ expect_equal(alias_mixed(x()), x() + rev(x()), info = "x = x + rev(x)")
17341734
expect_equal(alias_sapply(x()), x() - x()[1], info = "x = sapply(x, <reads x[0]>)")
17351735
expect_equal(alias_elementwise(x()), x() * 2 + x(), info = "x = x * 2 + x")
17361736
expect_equal(alias_range_shift(x()), c(1, 1, 2, 3, 4), info = "x[1:n-1] = head(x, n-1)")
1737+
expect_equal(alias_range_range(x()), c(1, 1, 2, 3, 4), info = "x[1:n-1] = x[0:n-2]")
1738+
expect_equal(alias_range_range_add(x()), c(1, 3, 5, 7, 9), info = "x[1:n-1] += x[0:n-2]")
17371739
expect_equal(alias_range_rev(x()), rev(x()), info = "x[0:n-1] = rev(x)")
17381740
expect_equal(alias_range_add_rev(x()), x() + rev(x()), info = "x[0:n-1] += rev(x)")
17391741
m <- function() matrix(c(1, 2, 3, 4, 5, 6), 3)
@@ -1761,7 +1763,7 @@ expect_equal(
17611763
c(vector = TRUE, arith = TRUE, math = TRUE, ifelse = TRUE,
17621764
rev = FALSE, arith_rev = FALSE, head = FALSE,
17631765
column_vector = TRUE, column_column = TRUE, column_row = FALSE,
1764-
row_row = TRUE, row_column = FALSE, range_range = FALSE),
1766+
row_row = TRUE, row_column = FALSE, range_range = FALSE, seq = TRUE),
17651767
info = "traits::is_elementwise"
17661768
)
17671769

@@ -1780,6 +1782,7 @@ expect_error(length_ifelse(c(TRUE, FALSE), c(1, 2), c(1, 2, 3)), "different leng
17801782
expect_equal(length_range(c(1, 2, 3, 4, 5), c(7, 8, 9)), c(7, 8, 9, 4, 5), info = "x[0:2] = y")
17811783
expect_error(length_range(c(1, 2, 3, 4, 5), c(7, 8)), "cannot assign", info = "x[0:2] = <shorter y>")
17821784
expect_error(length_range(c(1, 2, 3, 4, 5), c(6, 7, 8, 9)), "cannot assign", info = "x[0:2] = <longer y>")
1785+
expect_error(length_range_range(c(1, 2, 3, 4, 5)), "cannot assign", info = "x[0:1] = x[0:3]")
17831786
expect_error(length_column(matrix(1, 3, 2), c(7, 8)), "cannot assign", info = "m(_, 0) = <shorter y>")
17841787
expect_error(length_row(matrix(1, 3, 2), c(7, 8, 9)), "cannot assign", info = "m(0, _) = <longer y>")
17851788

0 commit comments

Comments
 (0)