-
Notifications
You must be signed in to change notification settings - Fork 991
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
116 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,111 +1,98 @@ | ||
#include "data.table.h" | ||
#include <Rdefines.h> | ||
|
||
static double l=0.0, u=0.0; | ||
|
||
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); | ||
} | ||
|
||
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); | ||
} | ||
|
||
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); | ||
} | ||
|
||
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); | ||
} | ||
|
||
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)); | ||
} | ||
|
||
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)); | ||
} | ||
|
||
static Rboolean double_upper_closed(SEXP x, R_len_t i) { | ||
return (ISNAN(REAL(x)[i]) || REAL(x)[i] <= u ? NA_LOGICAL : FALSE); | ||
} | ||
|
||
static Rboolean double_upper_open(SEXP x, R_len_t i) { | ||
return (ISNAN(REAL(x)[i]) || REAL(x)[i] < u ? NA_LOGICAL : FALSE); | ||
} | ||
|
||
static Rboolean double_lower_closed(SEXP x, R_len_t i) { | ||
return (ISNAN(REAL(x)[i]) || REAL(x)[i] >= l ? NA_LOGICAL : FALSE); | ||
} | ||
|
||
static Rboolean double_lower_open(SEXP x, R_len_t i) { | ||
return (ISNAN(REAL(x)[i]) || REAL(x)[i] > l ? NA_LOGICAL : FALSE); | ||
} | ||
|
||
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)); | ||
} | ||
|
||
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)); | ||
} | ||
|
||
SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP bounds) { | ||
|
||
R_len_t i, nx = length(x), nl = length(lower), nu = length(upper); | ||
l = 0.0; u = 0.0; | ||
SEXP ans; | ||
Rboolean (*flower)(), (*fupper)(), (*fboth)(); | ||
R_len_t nx = length(x), nl = length(lower), nu = length(upper); | ||
if (!nx || !nl || !nu) | ||
return (allocVector(LGLSXP, 0)); | ||
if (nl != 1 && nl != nx) | ||
error("length(lower) (%d) must be either 1 or length(x) (%d)", nl, nx); | ||
if (nu != 1 && nu != nx) | ||
error("length(upper) (%d) must be either 1 or length(x) (%d)", nu, nx); | ||
if (!isLogical(bounds) || LOGICAL(bounds)[0] == NA_LOGICAL) | ||
error("incbounds must be logical TRUE/FALSE."); | ||
error("incbounds must be logical TRUE/FALSE."); // # nocov | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
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; | ||
flower = isInteger(x) ? &int_lower_closed : &double_lower_closed; | ||
fboth = isInteger(x) ? &int_both_closed : &double_both_closed; | ||
} else { | ||
fupper = isInteger(x) ? &int_upper_open : &double_upper_open; | ||
flower = isInteger(x) ? &int_lower_open : &double_lower_open; | ||
fboth = isInteger(x) ? &int_both_open : &double_both_open; | ||
bool integer=true; | ||
if (isReal(x) || isReal(lower) || isReal(upper)) { | ||
if (inherits(x,"integer64") || inherits(lower,"integer64") || inherits(upper,"integer64")) { | ||
error("Internal error: one or more of x, lower and upper is type integer64 but this should have been caught by between() at R level."); // # nocov | ||
} | ||
integer=false; | ||
lower = PROTECT(coerceVector(lower, REALSXP)); // these coerces will convert NA appropriately | ||
upper = PROTECT(coerceVector(upper, REALSXP)); | ||
x = PROTECT(coerceVector(x, REALSXP)); | ||
nprotect += 3; | ||
} | ||
|
||
if ( ISNAN(REAL(lower)[0]) ) { | ||
if ( ISNAN(REAL(upper)[0]) ) { | ||
// TODO: sweep through lower and upper ensuring lower<=upper (inc bounds) and no lower>upper or lower==INT_MAX | ||
|
||
const bool recycleLow = LENGTH(lower)==1; | ||
const bool recycleUpp = LENGTH(upper)==1; | ||
const bool open = !LOGICAL(bounds)[0]; | ||
SEXP ans = PROTECT(allocVector(LGLSXP, nx)); nprotect++; | ||
int *restrict ansp = LOGICAL(ans); | ||
if (integer) { | ||
const int *lp = INTEGER(lower); | ||
const int *up = INTEGER(upper); | ||
const int *xp = INTEGER(x); | ||
if (recycleLow && recycleUpp) { | ||
const int l = lp[0] + open; // +open so we can always use >= and <=. NA_INTEGER+1 == -INT_MAX == INT_MIN+1 (so NA limit handled by this too) | ||
const int u = up[0]==NA_INTEGER ? INT_MAX : up[0] - open; | ||
#pragma omp parallel for num_threads(getDTthreads()) | ||
for (i=0; i<nx; i++) LOGICAL(ans)[i] = NA_LOGICAL; | ||
} else { | ||
for (int i=0; i<nx; i++) { | ||
int elem = xp[i]; | ||
ansp[i] = elem==NA_INTEGER ? NA_LOGICAL : (l<=elem && elem<=u); | ||
} | ||
} | ||
else { | ||
const int lowMask = recycleLow ? 0 : INT_MAX; | ||
const int uppMask = recycleUpp ? 0 : INT_MAX; | ||
#pragma omp parallel for num_threads(getDTthreads()) | ||
for (i=0; i<nx; i++) LOGICAL(ans)[i] = fupper(x, i); | ||
for (int i=0; i<nx; i++) { | ||
int elem = xp[i]; | ||
int l = lp[i&lowMask] +open; | ||
int u = up[i&uppMask]; | ||
u = (u==NA_INTEGER) ? INT_MAX : u-open; | ||
ansp[i] = elem==NA_INTEGER ? NA_LOGICAL : (l<=elem && elem<=u); | ||
} | ||
} | ||
} else { | ||
if ( ISNAN(REAL(upper)[0]) ) { | ||
#pragma omp parallel for num_threads(getDTthreads()) | ||
for (i=0; i<nx; i++) LOGICAL(ans)[i] = flower(x, i); | ||
} else { | ||
// type real | ||
const double *lp = REAL(lower); | ||
const double *up = REAL(upper); | ||
const double *xp = REAL(x); | ||
if (recycleLow && recycleUpp) { | ||
const double l = isnan(lp[0]) ? -INFINITY : lp[0]; | ||
const double u = isnan(up[0]) ? INFINITY : up[0]; | ||
if (open) { | ||
#pragma omp parallel for num_threads(getDTthreads()) | ||
for (int i=0; i<nx; i++) { | ||
double elem = xp[i]; | ||
ansp[i] = isnan(elem) ? NA_LOGICAL : (l<elem && elem<u); | ||
} | ||
} else { | ||
#pragma omp parallel for num_threads(getDTthreads()) | ||
for (int i=0; i<nx; i++) { | ||
double elem = xp[i]; | ||
ansp[i] = isnan(elem) ? NA_LOGICAL : (l<=elem && elem<=u); | ||
} | ||
} | ||
} | ||
else { | ||
const int lowMask = recycleLow ? 0 : INT_MAX; | ||
const int uppMask = recycleUpp ? 0 : INT_MAX; | ||
#pragma omp parallel for num_threads(getDTthreads()) | ||
for (i=0; i<nx; i++) LOGICAL(ans)[i] = fboth(x, i); | ||
for (int i=0; i<nx; i++) { | ||
double elem = xp[i]; | ||
double l = lp[i&lowMask]; | ||
double u = up[i&uppMask]; | ||
if (isnan(l)) l=-INFINITY; | ||
if (isnan(u)) u= INFINITY; | ||
ansp[i] = isnan(elem) ? NA_LOGICAL : (open ? l<elem && elem<u : l<=elem && elem<=u); | ||
} | ||
} | ||
} | ||
UNPROTECT(nprotect); | ||
return(ans); | ||
} | ||
|
this is not an internal error, so should be tested instead of
nocov
, will amend when resolving #3516