diff --git a/src/between.c b/src/between.c index 678016fd2e..19d848c327 100644 --- a/src/between.c +++ b/src/between.c @@ -3,51 +3,51 @@ static double l=0.0, u=0.0; -Rboolean int_upper_closed(SEXP x, R_len_t i) { +static Rboolean int_upper_closed(SEXP x, R_len_t i) { return (INTEGER(x)[i] == NA_INTEGER || (double)INTEGER(x)[i] <= u ? NA_LOGICAL : FALSE); } -Rboolean int_upper_open(SEXP x, R_len_t i) { +static Rboolean int_upper_open(SEXP x, R_len_t i) { return (INTEGER(x)[i] == NA_INTEGER || (double)INTEGER(x)[i] < u ? NA_LOGICAL : FALSE); } -Rboolean int_lower_closed(SEXP x, R_len_t i) { +static Rboolean int_lower_closed(SEXP x, R_len_t i) { return (INTEGER(x)[i] == NA_INTEGER || (double)INTEGER(x)[i] >= l ? NA_LOGICAL : FALSE); } -Rboolean int_lower_open(SEXP x, R_len_t i) { +static Rboolean int_lower_open(SEXP x, R_len_t i) { return (INTEGER(x)[i] == NA_INTEGER || (double)INTEGER(x)[i] > l ? NA_LOGICAL : FALSE); } -Rboolean int_both_closed(SEXP x, R_len_t i) { +static Rboolean int_both_closed(SEXP x, R_len_t i) { return (INTEGER(x)[i] == NA_INTEGER ? NA_LOGICAL : ((double)INTEGER(x)[i] >= l && (double)INTEGER(x)[i] <= u)); } -Rboolean int_both_open(SEXP x, R_len_t i) { +static Rboolean int_both_open(SEXP x, R_len_t i) { return (INTEGER(x)[i] == NA_INTEGER ? NA_LOGICAL : ((double)INTEGER(x)[i] > l && (double)INTEGER(x)[i] < u)); } -Rboolean double_upper_closed(SEXP x, R_len_t i) { +static Rboolean double_upper_closed(SEXP x, R_len_t i) { return (ISNAN(REAL(x)[i]) || REAL(x)[i] <= u ? NA_LOGICAL : FALSE); } -Rboolean double_upper_open(SEXP x, R_len_t i) { +static Rboolean double_upper_open(SEXP x, R_len_t i) { return (ISNAN(REAL(x)[i]) || REAL(x)[i] < u ? NA_LOGICAL : FALSE); } -Rboolean double_lower_closed(SEXP x, R_len_t i) { +static Rboolean double_lower_closed(SEXP x, R_len_t i) { return (ISNAN(REAL(x)[i]) || REAL(x)[i] >= l ? NA_LOGICAL : FALSE); } -Rboolean double_lower_open(SEXP x, R_len_t i) { +static Rboolean double_lower_open(SEXP x, R_len_t i) { return (ISNAN(REAL(x)[i]) || REAL(x)[i] > l ? NA_LOGICAL : FALSE); } -Rboolean double_both_closed(SEXP x, R_len_t i) { +static Rboolean double_both_closed(SEXP x, R_len_t i) { return (ISNAN(REAL(x)[i]) ? NA_LOGICAL : (REAL(x)[i] >= l && REAL(x)[i] <= u)); } -Rboolean double_both_open(SEXP x, R_len_t i) { +static Rboolean double_both_open(SEXP x, R_len_t i) { return (ISNAN(REAL(x)[i]) ? NA_LOGICAL : (REAL(x)[i] > l && REAL(x)[i] < u)); } @@ -66,11 +66,18 @@ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP bounds) { if (!isLogical(bounds) || LOGICAL(bounds)[0] == NA_LOGICAL) error("incbounds must be logical TRUE/FALSE."); + int nprotect = 0; + if (ALTREP(x)) { x = PROTECT(duplicate(x)); nprotect++; } + if (ALTREP(lower)) { lower = PROTECT(duplicate(lower)); nprotect++; } + if (ALTREP(upper)) { upper = PROTECT(duplicate(upper)); nprotect++; } + if (ALTREP(bounds)) { bounds = PROTECT(duplicate(bounds)); nprotect++; } + // no support for int64 yet (only handling most common cases) // coerce to also get NA values properly lower = PROTECT(coerceVector(lower, REALSXP)); l = REAL(lower)[0]; upper = PROTECT(coerceVector(upper, REALSXP)); u = REAL(upper)[0]; ans = PROTECT(allocVector(LGLSXP, nx)); + nprotect += 3; if (LOGICAL(bounds)[0]) { fupper = isInteger(x) ? &int_upper_closed : &double_upper_closed; @@ -99,6 +106,6 @@ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP bounds) { for (i=0; i maxSize) maxSize=SIZEOF(v); + if (ALTREP(v)) SET_VECTOR_ELT(x,i,duplicate(v)); // expand compact vector in place, ready for reordering by reference } } else { if (SIZEOF(x)!=4 && SIZEOF(x)!=8) error("reorder accepts vectors but this non-VECSXP is type '%s' which isn't yet supported", type2char(TYPEOF(x))); + if (ALTREP(x)) error("Internal error in reorder.c: cannot reorder an ALTREP vector. Please see NEWS item 2 in v1.11.4 and report this as a bug."); maxSize = SIZEOF(x); nrow = length(x); ncol = 1; } if (!isInteger(order)) error("order must be an integer vector"); if (length(order) != nrow) error("nrow(x)[%d]!=length(order)[%d]",nrow,length(order)); + int nprotect = 0; + if (ALTREP(order)) { order=PROTECT(duplicate(order)); nprotect++; } // TODO: how to fetch range of ALTREP compact vector R_len_t start = 0; while (start