diff --git a/src/between.c b/src/between.c index 132560196..5a1825c61 100644 --- a/src/between.c +++ b/src/between.c @@ -8,7 +8,7 @@ */ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAboundsArg, SEXP checkArg) { int nprotect = 0; - R_len_t nx = length(x), nl = length(lower), nu = length(upper); + const R_len_t nx = length(x), nl = length(lower), nu = length(upper); if (!nx || !nl || !nu) return (allocVector(LGLSXP, 0)); const int longest = MAX(MAX(nx, nl), nu); @@ -20,13 +20,13 @@ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAboundsArg, S const int longestBound = MAX(nl, nu); // just for when check=TRUE if (!IS_TRUE_OR_FALSE(incbounds)) error(_("%s must be TRUE or FALSE"), "incbounds"); - const bool open = !LOGICAL(incbounds)[0]; - if (!isLogical(NAboundsArg) || LOGICAL(NAboundsArg)[0]==FALSE) + const bool open = !LOGICAL_RO(incbounds)[0]; + if (!isLogical(NAboundsArg) || LOGICAL_RO(NAboundsArg)[0]==FALSE) error(_("NAbounds must be TRUE or NA")); - const bool NAbounds = LOGICAL(NAboundsArg)[0]==TRUE; + const bool NAbounds = LOGICAL_RO(NAboundsArg)[0]==TRUE; if (!IS_TRUE_OR_FALSE(checkArg)) error(_("%s must be TRUE or FALSE"), "check"); - const bool check = LOGICAL(checkArg)[0]; + const bool check = LOGICAL_RO(checkArg)[0]; const bool verbose = GetVerbose(); // check before potential coercion which ignores methods, #7164 @@ -70,13 +70,13 @@ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAboundsArg, S const int uppMask = recycleUpp ? 0 : INT_MAX; SEXP ans = PROTECT(allocVector(LGLSXP, longest)); nprotect++; int *restrict ansp = LOGICAL(ans); - double tic=omp_get_wtime(); + const double tic=omp_get_wtime(); switch (TYPEOF(x)) { case INTSXP: { - const int *lp = INTEGER(lower); - const int *up = INTEGER(upper); - const int *xp = INTEGER(x); + const int *lp = INTEGER_RO(lower); + const int *up = INTEGER_RO(upper); + const int *xp = INTEGER_RO(x); if (check) for (int i=0; iu) @@ -103,9 +103,9 @@ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAboundsArg, S case REALSXP: if (INHERITS(x, char_integer64)) { - const int64_t *lp = (int64_t *)REAL(lower); - const int64_t *up = (int64_t *)REAL(upper); - const int64_t *xp = (int64_t *)REAL(x); + const int64_t *lp = (const int64_t*)REAL_RO(lower); + const int64_t* up = (const int64_t*)REAL_RO(upper); + const int64_t* xp = (const int64_t*)REAL_RO(x); if (check) for (int i=0; iu) @@ -128,9 +128,9 @@ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAboundsArg, S } if (verbose) Rprintf(_("between parallel processing of integer64 took %8.3fs\n"), omp_get_wtime()-tic); } else { - const double *lp = REAL(lower); - const double *up = REAL(upper); - const double *xp = REAL(x); + const double *lp = REAL_RO(lower); + const double *up = REAL_RO(upper); + const double *xp = REAL_RO(x); if (check) for (int i=0; iu) diff --git a/src/bmerge.c b/src/bmerge.c index 5b778f19b..43e4f5608 100644 --- a/src/bmerge.c +++ b/src/bmerge.c @@ -26,7 +26,8 @@ Differences over standard binary search (e.g. bsearch in stdlib.h) : static const SEXP *idtVec, *xdtVec; static const int *icols, *xcols; static SEXP nqgrp; -static int ncol, *o, *xo, *retFirst, *retLength, *retIndex, *allLen1, *allGrp1, *rollends, ilen, anslen; +static int ncol, *o, *xo, *retFirst, *retLength, *retIndex, *allLen1, *allGrp1, ilen, anslen; +static const int* rollends; static int *op, nqmaxgrp; static int ctr, nomatch; // populating matches for non-equi joins enum {ALL, FIRST, LAST, ERR} mult = ALL; @@ -56,8 +57,8 @@ SEXP bmerge(SEXP idt, SEXP xdt, SEXP icolsArg, SEXP xcolsArg, SEXP xoArg, SEXP r if ((LENGTH(icolsArg)==0 || LENGTH(xcolsArg)==0) && LENGTH(idt)>0) // We let through LENGTH(i) == 0 for tests 2126.* internal_error(__func__, "icols and xcols must be non-empty integer vectors"); if (LENGTH(icolsArg) > LENGTH(xcolsArg)) internal_error(__func__, "length(icols) [%d] > length(xcols) [%d]", LENGTH(icolsArg), LENGTH(xcolsArg)); // # nocov - icols = INTEGER(icolsArg); - xcols = INTEGER(xcolsArg); + icols = INTEGER_RO(icolsArg); + xcols = INTEGER_RO(xcolsArg); xN = LENGTH(xdt) ? LENGTH(VECTOR_ELT(xdt,0)) : 0; iN = ilen = anslen = LENGTH(idt) ? LENGTH(VECTOR_ELT(idt,0)) : 0; ncol = LENGTH(icolsArg); // there may be more sorted columns in x than involved in the join @@ -94,7 +95,7 @@ SEXP bmerge(SEXP idt, SEXP xdt, SEXP icolsArg, SEXP xcolsArg, SEXP xoArg, SEXP r rollabs = fabs(roll); if (!isLogical(rollendsArg) || LENGTH(rollendsArg) != 2) error(_("rollends must be a length 2 logical vector")); - rollends = LOGICAL(rollendsArg); + rollends = LOGICAL_RO(rollendsArg); if (isNull(nomatchArg)) { nomatch=0; diff --git a/src/cj.c b/src/cj.c index 0598f94ea..753b79d58 100644 --- a/src/cj.c +++ b/src/cj.c @@ -24,7 +24,7 @@ SEXP cj(SEXP base_list) { switch(TYPEOF(source)) { case LGLSXP: case INTSXP: { - const int *restrict sourceP = INTEGER(source); + const int *restrict sourceP = INTEGER_RO(source); int *restrict targetP = INTEGER(target); #pragma omp parallel for num_threads(getDTthreads(thislen*eachrep, true)) // default static schedule so two threads won't write to same cache line in last column @@ -40,7 +40,7 @@ SEXP cj(SEXP base_list) { } } break; case REALSXP: { - const double *restrict sourceP = REAL(source); + const double *restrict sourceP = REAL_RO(source); double *restrict targetP = REAL(target); #pragma omp parallel for num_threads(getDTthreads(thislen*eachrep, true)) for (int i=0; i 1; // showProgress only if more than 1 group + const bool showProgress = LOGICAL_RO(showProgressArg)[0]==1 && ngrp > 1; // showProgress only if more than 1 group double startTime = (showProgress) ? wallclock() : 0; // For progress printing, startTime is set at the beginning double nextTime = (showProgress) ? startTime+3 : 0; // wait 3 seconds before printing progress defineVar(sym_BY, BY = PROTECT(allocVector(VECSXP, ngrpcols)), env); nprotect++; // PROTECT for rchk SEXP bynames = PROTECT(allocVector(STRSXP, ngrpcols)); nprotect++; // TO DO: do we really need bynames, can we assign names afterwards in one step? for (int i=0; i maxGrpSize) maxGrpSize = ilens[i]; } @@ -132,7 +132,7 @@ SEXP dogroups(SEXP dt, SEXP dtcols, SEXP groups, SEXP grpcols, SEXP jiscols, SEX for (s = ATTRIB(SD); s != R_NilValue && TAG(s)!=R_RowNamesSymbol; s = CDR(s)); // getAttrib0 basically but that's hidden in attrib.c; #loop_counter_not_local_scope_ok if (s==R_NilValue) error(_("row.names attribute of .SD not found")); rownames = CAR(s); - if (!isInteger(rownames) || LENGTH(rownames)!=2 || INTEGER(rownames)[0]!=NA_INTEGER) error(_("row.names of .SD isn't integer length 2 with NA as first item; i.e., .set_row_names(). [%s %d %d]"),type2char(TYPEOF(rownames)),LENGTH(rownames),INTEGER(rownames)[0]); + if (!isInteger(rownames) || LENGTH(rownames)!=2 || INTEGER_RO(rownames)[0]!=NA_INTEGER) error(_("row.names of .SD isn't integer length 2 with NA as first item; i.e., .set_row_names(). [%s %d %d]"),type2char(TYPEOF(rownames)),LENGTH(rownames),INTEGER_RO(rownames)[0]); // fetch names of .SD and prepare symbols. In case they are copied-on-write by user assigning to those variables // using <- in j (which is valid, useful and tested), they are repointed to the .SD cols for each group. @@ -149,7 +149,7 @@ SEXP dogroups(SEXP dt, SEXP dtcols, SEXP groups, SEXP grpcols, SEXP jiscols, SEX internal_error(__func__, "SDall %d length = %d != %d", i+1, LENGTH(this), maxGrpSize); // # nocov nameSyms[i] = install(CHAR(STRING_ELT(names, i))); // fixes http://stackoverflow.com/questions/14753411/why-does-data-table-lose-class-definition-in-sd-after-group-by - copyMostAttrib(VECTOR_ELT(dt,INTEGER(dtcols)[i]-1), this); // not names, otherwise test 778 would fail + copyMostAttrib(VECTOR_ELT(dt,INTEGER_RO(dtcols)[i]-1), this); // not names, otherwise test 778 would fail SET_TRUELENGTH(this, -maxGrpSize); // marker for anySpecialStatic(); see its comments } @@ -170,8 +170,8 @@ SEXP dogroups(SEXP dt, SEXP dtcols, SEXP groups, SEXP grpcols, SEXP jiscols, SEX Rboolean jexpIsSymbolOtherThanSD = (isSymbol(jexp) && strcmp(CHAR(PRINTNAME(jexp)),".SD")!=0); // test 559 ansloc = 0; - const int *istarts = INTEGER(starts); - const int *iorder = INTEGER(order); + const int *istarts = INTEGER_RO(starts); + const int *iorder = INTEGER_RO(order); // We just want to set anyNA for later. We do it only once for the whole operation // because it is a rare edge case for it to be true. See #4892. @@ -205,15 +205,15 @@ SEXP dogroups(SEXP dt, SEXP dtcols, SEXP groups, SEXP grpcols, SEXP jiscols, SEX } if (length(iSD) && length(VECTOR_ELT(iSD, 0))/*#4364*/) for (int j=0; j=0 && nrowgroups) for (int j=0; j=0) { for (int j=0; j 1) ++nDimensions; + for (int d=0; d 1) ++nDimensions; UNPROTECT(1); if (nDimensions > 1) error(_("Entry %d for group %d in j=list(...) is an array with %d dimensions > 1, which is disallowed. \"Break\" the array yourself with c() or as.vector() if that is intentional."), j+1, i+1, nDimensions); @@ -304,14 +304,14 @@ SEXP dogroups(SEXP dt, SEXP dtcols, SEXP groups, SEXP grpcols, SEXP jiscols, SEX error(_("RHS of := is NULL during grouped assignment, but it's not possible to delete parts of a column.")); int vlen = length(RHS); if (vlen>1 && vlen!=grpn) { - SEXP colname = isNull(VECTOR_ELT(dt, INTEGER(lhs)[j]-1)) ? STRING_ELT(newnames, INTEGER(lhs)[j]-origncol-1) : STRING_ELT(dtnames,INTEGER(lhs)[j]-1); + SEXP colname = isNull(VECTOR_ELT(dt, INTEGER_RO(lhs)[j]-1)) ? STRING_ELT(newnames, INTEGER_RO(lhs)[j]-origncol-1) : STRING_ELT(dtnames,INTEGER_RO(lhs)[j]-1); error(_("Supplied %d items to be assigned to group %d of size %d in column '%s'. The RHS length must either be 1 (single values are ok) or match the LHS length exactly. If you wish to 'recycle' the RHS please use rep() explicitly to make this intent clear to readers of your code."),vlen,i+1,grpn,CHAR(colname)); // e.g. in #91 `:=` did not issue recycling warning during grouping. Now it is error not warning. } } int n = LENGTH(VECTOR_ELT(dt, 0)); for (int j=0; jmax) max=tmp; else if (tmp=0; i--) { - uint8_t thisx = radix 2) error(_("Must be 2, 1 or 0")); + if (INTEGER(droundArg)[0] < 0 || INTEGER_RO(droundArg)[0] > 2) error(_("Must be 2, 1 or 0")); int oldRound = dround; - dround = INTEGER(droundArg)[0]; + dround = INTEGER_RO(droundArg)[0]; dmask = dround ? 1 << (8*dround-1) : 0; return ScalarInteger(oldRound); } @@ -496,7 +496,7 @@ SEXP forder(SEXP DT, SEXP by, SEXP retGrpArg, SEXP retStatsArg, SEXP sortGroupsA STOP(_("'order' length (%d) is different to by='s length (%d)"), LENGTH(ascArg), LENGTH(by)); SEXP recycleAscArg = PROTECT(allocVector(INTSXP, LENGTH(by))); n_protect++; for (int j=0; j length(DT)) internal_error_with_cleanup(__func__, "'by' value %d out of range [1,%d]", by_i, length(DT)); // # nocov # R forderv already catch that using C colnamesInt if ( nrow != length(VECTOR_ELT(DT, by_i-1)) ) - STOP(_("Column %d is length %d which differs from length of column 1 (%d), are you attempting to order by a list column?\n"), INTEGER(by)[i], length(VECTOR_ELT(DT, INTEGER(by)[i]-1)), nrow); + STOP(_("Column %d is length %d which differs from length of column 1 (%d), are you attempting to order by a list column?\n"), INTEGER_RO(by)[i], length(VECTOR_ELT(DT, INTEGER_RO(by)[i]-1)), nrow); if (TYPEOF(VECTOR_ELT(DT, by_i-1)) == CPLXSXP) n_cplx++; } if (!IS_TRUE_OR_FALSE(retGrpArg)) STOP(_("retGrp must be TRUE or FALSE")); // # nocov # covered in reuseSorting forder - retgrp = LOGICAL(retGrpArg)[0]==TRUE; + retgrp = LOGICAL_RO(retGrpArg)[0]==TRUE; if (!IS_TRUE_OR_FALSE(retStatsArg)) STOP(_("retStats must be TRUE or FALSE")); // # nocov # covered in reuseSorting forder - retstats = LOGICAL(retStatsArg)[0]==TRUE; + retstats = LOGICAL_RO(retStatsArg)[0]==TRUE; if (!retstats && retgrp) error(_("retStats must be TRUE whenever retGrp is TRUE")); // # nocov # covered in reuseSorting forder if (!IS_TRUE_OR_FALSE(sortGroupsArg)) STOP(_("sort must be TRUE or FALSE")); // # nocov # covered in reuseSorting forder - sortType = LOGICAL(sortGroupsArg)[0]==TRUE; // if sortType is 1, it is later flipped between +1/-1 according to ascArg. Otherwise ascArg is ignored when sortType==0 + sortType = LOGICAL_RO(sortGroupsArg)[0]==TRUE; // if sortType is 1, it is later flipped between +1/-1 according to ascArg. Otherwise ascArg is ignored when sortType==0 if (!retgrp && !sortType) STOP(_("At least one of retGrp= or sort= must be TRUE")); if (!isLogical(naArg) || LENGTH(naArg) != 1) STOP(_("na.last must be logical TRUE, FALSE or NA of length 1")); // # nocov # covered in reuseSorting forder - nalast = (LOGICAL(naArg)[0] == NA_LOGICAL) ? -1 : LOGICAL(naArg)[0]; // 1=na last, 0=na first (default), -1=remove na + nalast = (LOGICAL_RO(naArg)[0] == NA_LOGICAL) ? -1 : LOGICAL_RO(naArg)[0]; // 1=na last, 0=na first (default), -1=remove na if (nrow==0) { // empty vector or 0-row DT is always sorted @@ -553,8 +553,8 @@ SEXP forder(SEXP DT, SEXP by, SEXP retGrpArg, SEXP retStatsArg, SEXP sortGroupsA TEND(1) savetl_init(); // from now on use Error not error - int ncol=length(by); - int keyAlloc = (ncol+n_cplx)*8 + 1; // +1 for NULL to mark end; calloc to initialize with NULLs + const int ncol=length(by); + const int keyAlloc = (ncol+n_cplx)*8 + 1; // +1 for NULL to mark end; calloc to initialize with NULLs key = calloc(keyAlloc, sizeof(*key)); // needs to be before loop because part II relies on part I, column-by-column. if (!key) STOP(_("Unable to allocate %"PRIu64" bytes of working memory"), (uint64_t)keyAlloc*sizeof(*key)); // # nocov @@ -568,19 +568,19 @@ SEXP forder(SEXP DT, SEXP by, SEXP retGrpArg, SEXP retStatsArg, SEXP sortGroupsA TEND(2); for (int col=0; collength(x)) STOP(_("issorted 'by' [%d] out of range [1,%d]"), INTEGER(by)[0], length(x)); - x = VECTOR_ELT(x, INTEGER(by)[0]-1); + if (INTEGER(by)[0]<1 || INTEGER_RO(by)[0]>length(x)) STOP(_("issorted 'by' [%d] out of range [1,%d]"), INTEGER_RO(by)[0], length(x)); + x = VECTOR_ELT(x, INTEGER_RO(by)[0]-1); } const int n = length(x); if (n <= 1) return(ScalarLogical(TRUE)); @@ -1416,10 +1416,10 @@ SEXP issorted(SEXP x, SEXP by) } break; case REALSXP : if (inherits(x,"integer64")) { - int64_t *xd = (int64_t *)REAL(x); + const int64_t *xd = (const int64_t*)REAL_RO(x); while (i=xd[i-1]) i++; } else { - double *xd = REAL(x); + const double *xd = REAL_RO(x); while (i=dtwiddle(xd[i-1])) i++; // TODO: change to loop over any NA or -Inf at the beginning and then proceed without dtwiddle() (but rounding) } break; @@ -1459,11 +1459,11 @@ SEXP issorted(SEXP x, SEXP by) switch(TYPEOF(col)) { case INTSXP: case LGLSXP: types[j] = 0; - ptrs[j] = (const char *)INTEGER(col); + ptrs[j] = (const char *)INTEGER_RO(col); break; case REALSXP: types[j] = inherits(col, "integer64") ? 2 : 1; - ptrs[j] = (const char *)REAL(col); + ptrs[j] = (const char *)REAL_RO(col); break; case STRSXP: types[j] = 3; @@ -1522,7 +1522,7 @@ SEXP isOrderedSubset(SEXP x, SEXP nrowArg) if (!isInteger(nrowArg) || LENGTH(nrowArg)!=1) error(_("nrow must be integer vector length 1")); const int nrow = INTEGER(nrowArg)[0]; if (nrow<0) error(_("nrow==%d but must be >=0"), nrow); - const int *xd = INTEGER(x), xlen=LENGTH(x); + const int *xd = INTEGER_RO(x), xlen=LENGTH(x); for (int i=0, last=INT_MIN; i0 || attr(idx, "anyinfnan")>0 bool idxAnyNF(SEXP idx) { - return INTEGER(getAttrib(idx, sym_anyna))[0]>0 || INTEGER(getAttrib(idx, sym_anyinfnan))[0]>0; + return INTEGER_RO(getAttrib(idx, sym_anyna))[0]>0 || INTEGER_RO(getAttrib(idx, sym_anyinfnan))[0]>0; } // forder, re-use existing key or index if possible, otherwise call forder @@ -1681,23 +1681,23 @@ SEXP forderReuseSorting(SEXP DT, SEXP by, SEXP retGrpArg, SEXP retStatsArg, SEXP error(_("DT is NULL")); if (!IS_TRUE_OR_FALSE(retGrpArg)) error(_("retGrp must be TRUE or FALSE")); - bool retGrp = (bool)LOGICAL(retGrpArg)[0]; + bool retGrp = (bool)LOGICAL_RO(retGrpArg)[0]; if (!IS_TRUE_OR_FALSE(retStatsArg)) error(_("retStats must be TRUE or FALSE")); - bool retStats = (bool)LOGICAL(retStatsArg)[0]; + bool retStats = (bool)LOGICAL_RO(retStatsArg)[0]; if (!retStats && retGrp) error(_("retStats must be TRUE whenever retGrp is TRUE")); // retStats doesnt cost anything and it will be much easier to optimize use of index if (!IS_TRUE_OR_FALSE(sortGroupsArg)) error(_("sort must be TRUE or FALSE")); - bool sortGroups = (bool)LOGICAL(sortGroupsArg)[0]; + bool sortGroups = (bool)LOGICAL_RO(sortGroupsArg)[0]; if (!isLogical(naArg) || LENGTH(naArg) != 1) error(_("na.last must be logical TRUE, FALSE or NA of length 1")); - bool na = (bool)LOGICAL(naArg)[0]; + bool na = (bool)LOGICAL_RO(naArg)[0]; if (!isInteger(ascArg)) error(_("order must be integer")); // # nocov # coerced to int in R if (!isLogical(reuseSortingArg) || LENGTH(reuseSortingArg) != 1) error(_("reuseSorting must be logical TRUE, FALSE or NA of length 1")); - int reuseSorting = LOGICAL(reuseSortingArg)[0]; + int reuseSorting = LOGICAL_RO(reuseSortingArg)[0]; if (!length(DT)) return allocVector(INTSXP, 0); int opt = -1; // -1=unknown, 0=none, 1=keyOpt, 2=idxOpt diff --git a/src/frank.c b/src/frank.c index 997ec79e4..35d8ccf83 100644 --- a/src/frank.c +++ b/src/frank.c @@ -28,12 +28,12 @@ SEXP dt_na(SEXP x, SEXP cols) error(_("Column %d of input list x is length %d, inconsistent with first column of that item which is length %d."), i+1,length(v),n); switch (TYPEOF(v)) { case LGLSXP: { - const int *iv = LOGICAL(v); + const int *iv = LOGICAL_RO(v); for (int j=0; jLENGTH(x)) error(_("Item %d of 'cols' is %d which is outside 1-based range [1,ncol(x)=%d]"), i+1, elem, LENGTH(x)); if (!n) n = length(VECTOR_ELT(x, elem-1)); @@ -205,11 +205,11 @@ SEXP anyNA(SEXP x, SEXP cols) { j=0; switch (TYPEOF(v)) { case LGLSXP: { - const int *iv = LOGICAL(v); + const int *iv = LOGICAL_RO(v); while(j= 0.0) - args.nrowLimit = (int64_t)(REAL(nrowLimitArg)[0]); + if (R_FINITE(REAL_RO(nrowLimitArg)[0]) && REAL_RO(nrowLimitArg)[0] >= 0.0) + args.nrowLimit = (int64_t)(REAL_RO(nrowLimitArg)[0]); - args.logical01 = LOGICAL(logical01Arg)[0]; - args.logicalYN = LOGICAL(logicalYNArg)[0]; + args.logical01 = LOGICAL_RO(logical01Arg)[0]; + args.logicalYN = LOGICAL_RO(logicalYNArg)[0]; { SEXP tt = PROTECT(GetOption1(sym_old_fread_datetime_character)); - args.oldNoDateTime = oldNoDateTime = isLogical(tt) && LENGTH(tt)==1 && LOGICAL(tt)[0] == TRUE; + args.oldNoDateTime = oldNoDateTime = isLogical(tt) && LENGTH(tt)==1 && LOGICAL_RO(tt)[0] == TRUE; UNPROTECT(1); } args.skipNrow = -1; @@ -157,19 +157,19 @@ SEXP freadR( args.NAstrings = NAstrings; // here we use bool and rely on fread at R level to check these do not contain NA_LOGICAL - args.stripWhite = LOGICAL(stripWhiteArg)[0]; - args.skipEmptyLines = LOGICAL(skipEmptyLinesArg)[0]; + args.stripWhite = LOGICAL_RO(stripWhiteArg)[0]; + args.skipEmptyLines = LOGICAL_RO(skipEmptyLinesArg)[0]; const char *commentStr = CHAR(STRING_ELT(commentCharArg, 0)); args.comment = strlen(commentStr) == 0 ? '\0' : commentStr[0]; args.fill = INTEGER(fillArg)[0]; - args.showProgress = LOGICAL(showProgressArg)[0]; - if (INTEGER(nThreadArg)[0] < 1) - error("nThread(%d)<1", INTEGER(nThreadArg)[0]); // # notranslate - args.nth = (uint32_t)INTEGER(nThreadArg)[0]; + args.showProgress = LOGICAL_RO(showProgressArg)[0]; + if (INTEGER_RO(nThreadArg)[0] < 1) + error("nThread(%d)<1", INTEGER_RO(nThreadArg)[0]); // # notranslate + args.nth = (uint32_t)INTEGER_RO(nThreadArg)[0]; args.verbose = verbose; args.warningsAreErrors = warningsAreErrors; - args.keepLeadingZeros = LOGICAL(keepLeadingZerosArgs)[0]; - args.noTZasUTC = LOGICAL(noTZasUTC)[0]; + args.keepLeadingZeros = LOGICAL_RO(keepLeadingZerosArgs)[0]; + args.noTZasUTC = LOGICAL_RO(noTZasUTC)[0]; // === extras used for callbacks === if (!isString(integer64Arg) || LENGTH(integer64Arg) != 1) error(_("'integer64' must be a single character string")); @@ -395,7 +395,7 @@ bool userOverride(int8_t *type, lenOff *colNames, const char *anchor, const int else itemsInt = PROTECT(coerceVector(items, INTSXP)); // UNPROTECTed directly just after this for loop. No nprotect++ here is correct. for (int j = 0; j < LENGTH(items); j++) { - const int colIdx = INTEGER(itemsInt)[j]; // NB: 1-based + const int colIdx = INTEGER_RO(itemsInt)[j]; // NB: 1-based if (colIdx == NA_INTEGER) { if (isString(items)) DTWARN(_("Column name '%s' (colClasses[[%d]][%d]) not found"), CHAR(STRING_ELT(items, j)), i + 1, j + 1); @@ -479,7 +479,7 @@ size_t allocateDT(int8_t *typeArg, int8_t *sizeArg, int ncolArg, int ndrop, size if (selectRank) { SEXP tt = PROTECT(allocVector(INTSXP, ncol - ndrop)); int *ttD = INTEGER(tt), rank = 1; - const int *rankD = INTEGER(selectRank); + const int *rankD = INTEGER_RO(selectRank); for (int i = 0; i < ncol; i++) if (type[i] != CT_DROP) ttD[rankD[i] - 1] = rank++; SET_VECTOR_ELT(RCHK, 3, selectRank = tt); // selectRank now holds the order not the rank (so its name is now misleading). setFinalNRow passes it to setcolorder diff --git a/src/frollR.c b/src/frollR.c index 71963e6f8..50740eee9 100644 --- a/src/frollR.c +++ b/src/frollR.c @@ -36,9 +36,9 @@ SEXP coerceK(SEXP obj, bool adaptive) { } else { error(_("'n' must be an integer")); } - int nk = length(obj); + const int nk = length(obj); R_len_t i = 0; - int *iik = INTEGER(ans); + const int *iik = INTEGER_RO(ans); while (i < nk && iik[i] >= 0) i++; if (i != nk) error(_("'n' must be non-negative integer values (>= 0)")); @@ -53,7 +53,7 @@ SEXP coerceK(SEXP obj, bool adaptive) { error(_("'n' must be an integer vector or list of integer vectors")); } } else { - int nk = length(obj); + const int nk = length(obj); ans = PROTECT(allocVector(VECSXP, nk)); protecti++; for (int i=0; i= 0) ii++; if (ii != nx) @@ -95,7 +95,7 @@ SEXP frollfunR(SEXP fun, SEXP xobj, SEXP kobj, SEXP fill, SEXP algo, SEXP align, if (!IS_TRUE_OR_FALSE(adaptive)) error(_("%s must be TRUE or FALSE"), "adaptive"); - bool badaptive = LOGICAL(adaptive)[0]; + const bool badaptive = LOGICAL_RO(adaptive)[0]; SEXP k = PROTECT(coerceK(kobj, badaptive)); protecti++; int nk = length(k); @@ -113,7 +113,7 @@ SEXP frollfunR(SEXP fun, SEXP xobj, SEXP kobj, SEXP fill, SEXP algo, SEXP align, if (!isLogical(hasnf) || length(hasnf)!=1) error(_("has.nf must be TRUE, FALSE or NA")); - if (LOGICAL(hasnf)[0]==FALSE && LOGICAL(narm)[0]) + if (LOGICAL_RO(hasnf)[0]==FALSE && LOGICAL_RO(narm)[0]) error(_("using has.nf FALSE and na.rm TRUE does not make sense, if you know there are non-finite values then use has.nf TRUE, otherwise leave it as default NA")); int ialign=-2; // decode align to integer @@ -175,15 +175,15 @@ SEXP frollfunR(SEXP fun, SEXP xobj, SEXP kobj, SEXP fill, SEXP algo, SEXP align, error(_("fill must be a vector of length 1")); if (!isInteger(fill) && !isReal(fill) && !isLogical(fill)) error(_("fill must be numeric or logical")); - double dfill = REAL(PROTECT(coerceAs(fill, PROTECT(ScalarReal(NA_REAL)), ScalarLogical(true))))[0]; protecti++; + const double dfill = REAL_RO(PROTECT(coerceAs(fill, PROTECT(ScalarReal(NA_REAL)), ScalarLogical(true))))[0]; protecti++; UNPROTECT(1); // as= input to coerceAs() - bool bnarm = LOGICAL(narm)[0]; + bool bnarm = LOGICAL_RO(narm)[0]; - int ihasnf = // plain C tri-state boolean as integer - LOGICAL(hasnf)[0]==NA_LOGICAL ? 0 : // hasnf NA, default, no info about NA - LOGICAL(hasnf)[0]==TRUE ? 1 : // hasnf TRUE, might be some NAs - -1; // hasnf FALSE, there should be no NAs // or there must be no NAs for rollmax #5441 + const int ihasnf = // plain C tri-state boolean as integer + LOGICAL_RO(hasnf)[0]==NA_LOGICAL ? 0 : // hasnf NA, default, no info about NA + LOGICAL_RO(hasnf)[0]==TRUE ? 1 : // hasnf TRUE, might be some NAs + -1; // hasnf FALSE, there should be no NAs // or there must be no NAs for rollmax #5441 unsigned int ialgo=-1; // decode algo to integer if (!strcmp(CHAR(STRING_ELT(algo, 0)), "fast")) @@ -193,7 +193,7 @@ SEXP frollfunR(SEXP fun, SEXP xobj, SEXP kobj, SEXP fill, SEXP algo, SEXP align, else internal_error(__func__, "invalid %s argument in %s function should have been caught earlier", "algo", "rolling"); // # nocov - bool par = nx*nk>1 && ialgo==0; + const bool par = nx*nk>1 && ialgo==0; if (verbose) { if (par) { Rprintf(_("%s: computing %d column(s) and %d window(s) in parallel\n"), __func__, nx, nk); @@ -226,14 +226,14 @@ SEXP frollfunR(SEXP fun, SEXP xobj, SEXP kobj, SEXP fill, SEXP algo, SEXP align, // helper called from R to generate adaptive window for irregularly spaced time series SEXP frolladapt(SEXP xobj, SEXP kobj, SEXP partial) { - bool p = LOGICAL(partial)[0]; - int n = INTEGER(kobj)[0]; + const bool p = LOGICAL_RO(partial)[0]; + const int n = INTEGER_RO(kobj)[0]; if (n == NA_INTEGER) error(_("'n' must not have NAs")); if (n < 1L) error(_("'n' must be positive integer values (>= 1)")); const int *x = INTEGER_RO(xobj); - int64_t len = XLENGTH(xobj); // can be 0 + const int64_t len = XLENGTH(xobj); // can be 0 if (len && x[0] == NA_INTEGER) error(_("index provided to 'x' must: be sorted, have no duplicates, have no NAs")); // error text for consistency to the one below diff --git a/src/fsort.c b/src/fsort.c index c43d69eee..b58bb6cde 100644 --- a/src/fsort.c +++ b/src/fsort.c @@ -96,7 +96,8 @@ int qsort_cmp(const void *a, const void *b) { return (xy); // largest first in a safe branchless way casting long to int } -static size_t shrinkMSB(size_t MSBsize, uint64_t *msbCounts, int *order, Rboolean verbose) { +static size_t shrinkMSB(size_t MSBsize, const uint64_t msbCounts[], const int order[], Rboolean verbose) +{ size_t oldMSBsize = MSBsize; while (MSBsize>0 && msbCounts[order[MSBsize-1]] < 2) MSBsize--; @@ -115,7 +116,7 @@ SEXP fsort(SEXP x, SEXP verboseArg) { t[0] = wallclock(); if (!IS_TRUE_OR_FALSE(verboseArg)) error(_("%s must be TRUE or FALSE"), "verbose"); - int verbose = LOGICAL(verboseArg)[0]; + const int verbose = LOGICAL_RO(verboseArg)[0]; if (!isNumeric(x)) error(_("x must be a vector of type double currently")); // TODO: not only detect if already sorted, but if it is, just return x to save the duplicate diff --git a/src/fwriteR.c b/src/fwriteR.c index 9cf870a35..7161b4e28 100644 --- a/src/fwriteR.c +++ b/src/fwriteR.c @@ -49,7 +49,7 @@ int getMaxCategLen(SEXP col) { const char *getCategString(SEXP col, int64_t row) { // the only writer that needs to have the header of the SEXP column, to get to the levels - int x = INTEGER(col)[row]; + int x = INTEGER_RO(col)[row]; return x == NA_INTEGER ? NULL : ENCODED_CHAR(STRING_ELT(getAttrib(col, R_LevelsSymbol), x - 1)); } @@ -75,7 +75,7 @@ static int32_t whichWriter(SEXP); void writeList(const void *col, int64_t row, char **pch) { SEXP v = ((const SEXP*)col)[row]; - int32_t wf = whichWriter(v); + const int32_t wf = whichWriter(v); if (TYPEOF(v) == VECSXP || wf == INT32_MIN || isFactor(v)) { internal_error(__func__, "TYPEOF(v)!=VECSXP && wf!=INT32_MIN && !isFactor(v); getMaxListItem should have caught this up front"); // # nocov } @@ -179,12 +179,12 @@ SEXP fwriteR( if (!isNewList(DF)) error(_("fwrite must be passed an object of type list; e.g. data.frame, data.table")); fwriteMainArgs args = { 0 }; // { 0 } to quieten valgrind's uninitialized, #4639 - args.is_gzip = LOGICAL(is_gzip_Arg)[0]; - args.gzip_level = INTEGER(gzip_level_Arg)[0]; - args.bom = LOGICAL(bom_Arg)[0]; + args.is_gzip = LOGICAL_RO(is_gzip_Arg)[0]; + args.gzip_level = INTEGER_RO(gzip_level_Arg)[0]; + args.bom = LOGICAL_RO(bom_Arg)[0]; args.yaml = CHAR(STRING_ELT(yaml_Arg, 0)); - args.verbose = LOGICAL(verbose_Arg)[0]; - args.forceDecimal = LOGICAL(forceDecimal_Arg)[0]; + args.verbose = LOGICAL_RO(verbose_Arg)[0]; + args.forceDecimal = LOGICAL_RO(forceDecimal_Arg)[0]; args.filename = CHAR(STRING_ELT(filename_Arg, 0)); args.ncol = length(DF); if (args.ncol == 0) { @@ -195,7 +195,7 @@ SEXP fwriteR( SEXP DFcoerced = DF; int protecti = 0; - dateTimeAs = INTEGER(dateTimeAs_Arg)[0]; + dateTimeAs = INTEGER_RO(dateTimeAs_Arg)[0]; if (dateTimeAs == DATETIMEAS_WRITECSV) { int i = 0; while(i < args.ncol && !INHERITS(VECTOR_ELT(DF,i), char_POSIXct)) i++; @@ -232,9 +232,9 @@ SEXP fwriteR( // just for use at this level to control whichWriter() when called now for each column and // when called later for cell items of list columns (if any) - dateTimeAs = INTEGER(dateTimeAs_Arg)[0]; - logical01 = LOGICAL(logical01_Arg)[0]; - args.scipen = INTEGER(scipen_Arg)[0]; + dateTimeAs = INTEGER_RO(dateTimeAs_Arg)[0]; + logical01 = LOGICAL_RO(logical01_Arg)[0]; + args.scipen = INTEGER_RO(scipen_Arg)[0]; utf8 = !strcmp(CHAR(STRING_ELT(encoding_Arg, 0)), "UTF-8"); native = !strcmp(CHAR(STRING_ELT(encoding_Arg, 0)), "native"); @@ -254,18 +254,18 @@ SEXP fwriteR( } SEXP cn = getAttrib(DF, R_NamesSymbol); - args.colNames = (LOGICAL(colNames_Arg)[0] && isString(cn)) ? DATAPTR_RO(cn) : NULL; + args.colNames = (LOGICAL_RO(colNames_Arg)[0] && isString(cn)) ? DATAPTR_RO(cn) : NULL; // user may want row names even when they don't exist (implied row numbers as row names) // so we need a separate boolean flag as well as the row names should they exist (rare) - args.doRowNames = LOGICAL(rowNames_Arg)[0]; + args.doRowNames = LOGICAL_RO(rowNames_Arg)[0]; args.rowNames = NULL; args.rowNameFun = 0; if (args.doRowNames) { SEXP rn = PROTECT(getAttrib(DF, R_RowNamesSymbol)); protecti++; if (isInteger(rn)) { - if (xlength(rn) != 2 || INTEGER(rn)[0] == NA_INTEGER) { + if (xlength(rn) != 2 || INTEGER_RO(rn)[0] == NA_INTEGER) { // not R's default rownames c(NA,-nrow) if (xlength(rn) != args.nrow) // Use (long long) to cast R_xlen_t to a fixed type to robustly avoid -Wformat compiler warnings, see #5768, PRId64 didn't work on M1 @@ -302,13 +302,13 @@ SEXP fwriteR( args.eol = CHAR(STRING_ELT(eol_Arg, 0)); args.na = CHAR(STRING_ELT(na_Arg, 0)); - args.doQuote = LOGICAL(quote_Arg)[0] == NA_LOGICAL ? INT8_MIN : LOGICAL(quote_Arg)[0] == 1; - args.qmethodEscape = LOGICAL(qmethodEscape_Arg)[0] == 1; + args.doQuote = LOGICAL_RO(quote_Arg)[0] == NA_LOGICAL ? INT8_MIN : LOGICAL_RO(quote_Arg)[0] == 1; + args.qmethodEscape = LOGICAL_RO(qmethodEscape_Arg)[0] == 1; args.squashDateTime = (dateTimeAs == 1); - args.append = LOGICAL(append_Arg)[0]; - args.buffMB = INTEGER(buffMB_Arg)[0]; - args.nth = INTEGER(nThread_Arg)[0]; - args.showProgress = LOGICAL(showProgress_Arg)[0]; + args.append = LOGICAL_RO(append_Arg)[0]; + args.buffMB = INTEGER_RO(buffMB_Arg)[0]; + args.nth = INTEGER_RO(nThread_Arg)[0]; + args.showProgress = LOGICAL_RO(showProgress_Arg)[0]; fwriteMain(args); diff --git a/src/gsumm.c b/src/gsumm.c index 5970f5919..1b0cc417e 100644 --- a/src/gsumm.c +++ b/src/gsumm.c @@ -2,9 +2,9 @@ //#include static int ngrp = 0; // number of groups -static int *grpsize = NULL; // size of each group, used by gmean (and gmedian) not gsum +static const int *grpsize = NULL; // size of each group, used by gmean (and gmedian) not gsum static int nrow = 0; // length of underlying x; same as length(ghigh) and length(glow) -static int *irows; // GForce support for subsets in 'i' (TODO: joins in 'i') +static const int *irows; // GForce support for subsets in 'i' (TODO: joins in 'i') static int irowslen = -1; // -1 is for irows = NULL static uint16_t *high=NULL, *low=NULL; // the group of each x item; a.k.a. which-group-am-I static int *restrict grp; // TODO: eventually this can be made local for gforce as won't be needed globally when all functions here use gather @@ -55,7 +55,7 @@ SEXP gforce(SEXP env, SEXP jsub, SEXP o, SEXP f, SEXP l, SEXP irowsArg) { irowslen = -1; } else if (isInteger(irowsArg)) { - irows = INTEGER(irowsArg); + irows = INTEGER_RO(irowsArg); irowslen = LENGTH(irowsArg); } else error(_("irowsArg is neither an integer vector nor NULL")); // # nocov @@ -63,7 +63,7 @@ SEXP gforce(SEXP env, SEXP jsub, SEXP o, SEXP f, SEXP l, SEXP irowsArg) { if (LENGTH(f) != ngrp) error("length(f)=%d != length(l)=%d", LENGTH(f), ngrp); // # notranslate nrow=0; - grpsize = INTEGER(l); + grpsize = INTEGER_RO(l); maxgrpn = 0; for (int i=0; i>bitshift) + 1; @@ -349,7 +349,7 @@ SEXP gsum(SEXP x, SEXP narmArg) { if (!IS_TRUE_OR_FALSE(narmArg)) error(_("%s must be TRUE or FALSE"), "na.rm"); - const bool narm = LOGICAL(narmArg)[0]; + const bool narm = LOGICAL_RO(narmArg)[0]; if (inherits(x, "factor")) error(_("%s is not meaningful for factors."), "sum"); const int n = (irowslen == -1) ? length(x) : irowslen; @@ -585,7 +585,7 @@ SEXP gmean(SEXP x, SEXP narmArg) error(_("%s is not meaningful for factors."), "mean"); if (!IS_TRUE_OR_FALSE(narmArg)) error(_("%s must be TRUE or FALSE"), "na.rm"); - const bool narm = LOGICAL(narmArg)[0]; + const bool narm = LOGICAL_RO(narmArg)[0]; const int n = (irowslen == -1) ? length(x) : irowslen; double started = wallclock(); const bool verbose=GetVerbose(); @@ -744,7 +744,7 @@ static SEXP gminmax(SEXP x, SEXP narm, const bool min) case LGLSXP: case INTSXP: { ans = PROTECT(allocVector(INTSXP, ngrp)); int *ansd = INTEGER(ans); - const int *xd = INTEGER(x); + const int *xd = INTEGER_RO(x); if (!LOGICAL(narm)[0]) { const int init = min ? INT_MAX : INT_MIN+1; // NA_INTEGER==INT_MIN checked in init.c for (int i=0; i0. This should have been caught before"); // # nocov - const int n=INTEGER(nArg)[0]; + const int n=INTEGER_RO(nArg)[0]; return n==1 ? glast(x) : gfirstlast(x, false, n, true); } SEXP ghead(SEXP x, SEXP nArg) { if (!isInteger(nArg) || LENGTH(nArg)!=1 || INTEGER(nArg)[0]<1) internal_error(__func__, "gtail is only implemented for n>0. This should have been caught before"); // # nocov - const int n=INTEGER(nArg)[0]; + const int n=INTEGER_RO(nArg)[0]; return n==1 ? gfirst(x) : gfirstlast(x, true, n, true); } SEXP gnthvalue(SEXP x, SEXP nArg) { if (!isInteger(nArg) || LENGTH(nArg)!=1 || INTEGER(nArg)[0]<1) internal_error(__func__, "`g[` (gnthvalue) is only implemented single value subsets with positive index, e.g., .SD[2]. This should have been caught before"); // # nocov - return gfirstlast(x, true, INTEGER(nArg)[0], false); + return gfirstlast(x, true, INTEGER_RO(nArg)[0], false); } // TODO: gwhich.min, gwhich.max @@ -1032,12 +1033,12 @@ static SEXP gvarsd1(SEXP x, SEXP narmArg, bool isSD) SEXP sub, ans = PROTECT(allocVector(REALSXP, ngrp)); double *ansd = REAL(ans); const bool nosubset = irowslen==-1; - const bool narm = LOGICAL(narmArg)[0]; + const bool narm = LOGICAL_RO(narmArg)[0]; switch(TYPEOF(x)) { case LGLSXP: case INTSXP: { sub = PROTECT(allocVector(INTSXP, maxgrpn)); // allocate once upfront int *subd = INTEGER(sub); - const int *xd = INTEGER(x); + const int *xd = INTEGER_RO(x); for (int i=0; i=count[i]) { // length check added by Matt to avoid SEGV in #2767 - INTEGER(tt)[0] = INTEGER(vv)[count[i]-1]; + INTEGER(tt)[0] = INTEGER_RO(vv)[count[i]-1]; } } @@ -197,7 +197,7 @@ SEXP lookup(SEXP ux, SEXP xlen, SEXP indices, SEXP gaps, SEXP overlaps, SEXP mul tt = VECTOR_ELT(type_lookup, i); int k=0; for (int j=count[i]-type_count[i]; j INTEGER(tmp2)[m] ) { + } else if ( INTEGER_RO(tmp1)[j] > INTEGER_RO(tmp2)[m] ) { ++m; } else ++j; } @@ -310,9 +310,9 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr tmp1 = VECTOR_ELT(lookup, k-1); tmp2 = VECTOR_ELT(lookup, to[i]-1); while (j INTEGER(tmp2)[m] ) { + } else if ( INTEGER_RO(tmp1)[j] > INTEGER_RO(tmp2)[m] ) { ++m; } else ++j; } @@ -326,7 +326,7 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr } } else totlen = rows; end1 = clock() - start; - if (LOGICAL(verbose)[0]) + if (LOGICAL_RO(verbose)[0]) Rprintf(_("First pass on calculating lengths in overlaps ... done in %8.3f seconds\n"), 1.0*(end1)/CLOCKS_PER_SEC); // ans[0] is the the position of 'query' and ans[1] is that of 'subject' @@ -351,7 +351,7 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr tmp2 = VECTOR_ELT(type_lookup, k-1); for (int j=0; j INTEGER(tmp2)[m] ) { + } else if ( INTEGER_RO(tmp1)[j] > INTEGER_RO(tmp2)[m] ) { ++m; } else ++j; } @@ -408,7 +408,7 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr tmp1 = VECTOR_ELT(lookup, k-1); for (int m=0; m INTEGER(tmp2)[m] ) { + } else if ( INTEGER_RO(tmp1)[j] > INTEGER_RO(tmp2)[m] ) { ++m; } else ++j; } @@ -476,7 +476,7 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr const int k = (from[i]>0) ? from[i] : 1; if (k <= to[i]) { // count[k-1] is equal to type_count[k-1] and will always be >0, so no length check necessary. tmp1 = VECTOR_ELT(lookup, k-1); - INTEGER(f2__)[thislen] = INTEGER(tmp1)[0]; + INTEGER(f2__)[thislen] = INTEGER_RO(tmp1)[0]; ++thislen; } if (len == thislen) { @@ -494,18 +494,18 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr const int k = from[i]; if (k == to[i]) { tmp1 = VECTOR_ELT(lookup, k-1); - INTEGER(f2__)[thislen] = INTEGER(tmp1)[0]; + INTEGER(f2__)[thislen] = INTEGER_RO(tmp1)[0]; ++thislen; } else if (k < to[i]) { int j=0, m=0; tmp1 = VECTOR_ELT(lookup, k-1); tmp2 = VECTOR_ELT(type_lookup, to[i]-1); while (j INTEGER(tmp2)[m] ) { + } else if (INTEGER_RO(tmp1)[j] > INTEGER_RO(tmp2)[m]) { ++m; } else ++j; } @@ -527,7 +527,7 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr for (int j=k; j<=to[i]; ++j) { if (type_count[j-1]) { tmp2 = VECTOR_ELT(type_lookup, j-1); - INTEGER(f2__)[thislen] = INTEGER(tmp2)[0]; + INTEGER(f2__)[thislen] = INTEGER_RO(tmp2)[0]; ++thislen; break; } @@ -547,18 +547,18 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr if (k > 0) { if (k == to[i] && count[k-1]) { tmp1 = VECTOR_ELT(lookup, k-1); - INTEGER(f2__)[thislen] = INTEGER(tmp1)[0]; + INTEGER(f2__)[thislen] = INTEGER_RO(tmp1)[0]; ++thislen; } else if (k < to[i]) { int j=0, m=0; tmp1 = VECTOR_ELT(lookup, k-1); tmp2 = VECTOR_ELT(lookup, to[i]-1); while (j INTEGER(tmp2)[m] ) { + } else if ( INTEGER_RO(tmp1)[j] > INTEGER_RO(tmp2)[m] ) { ++m;; } else ++j; } @@ -583,7 +583,7 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr const int k = (from[i]>0) ? from[i] : 1; if (k <= to[i]) { // count[k-1] is equal to type_count[k-1] and will always be >0, so no length check necessary. tmp1 = VECTOR_ELT(lookup, k-1); - INTEGER(f2__)[thislen] = INTEGER(tmp1)[count[k-1]-1]; + INTEGER(f2__)[thislen] = INTEGER_RO(tmp1)[count[k-1]-1]; ++thislen; } if (len == thislen) { @@ -609,18 +609,18 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr const int k = from[i]; if (k == to[i]) { tmp1 = VECTOR_ELT(lookup, k-1); - INTEGER(f2__)[thislen] = INTEGER(tmp1)[count[k-1]-1]; + INTEGER(f2__)[thislen] = INTEGER_RO(tmp1)[count[k-1]-1]; ++thislen; } else if (k < to[i]) { tmp1 = VECTOR_ELT(lookup, k-1); tmp2 = VECTOR_ELT(type_lookup, to[i]-1); int j=count[k-1]-1, m=type_count[to[i]-1]-1; // bug fix, k=from[i] but should be to[i] while (j>=0 && m>=0) { - if ( INTEGER(tmp1)[j] == INTEGER(tmp2)[m] ) { - INTEGER(f2__)[thislen] = INTEGER(tmp1)[j]; + if (INTEGER_RO(tmp1)[j] == INTEGER_RO(tmp2)[m]) { + INTEGER(f2__)[thislen] = INTEGER_RO(tmp1)[j]; ++thislen; --j; --m; break; - } else if ( INTEGER(tmp1)[j] < INTEGER(tmp2)[m] ) { + } else if (INTEGER_RO(tmp1)[j] < INTEGER_RO(tmp2)[m]) { --m; } else --j; } @@ -664,19 +664,19 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr if (k <= to[i]) { if (k==to[i] && count[k-1]) { tmp1 = VECTOR_ELT(lookup, k-1); - INTEGER(f2__)[thislen] = INTEGER(tmp1)[count[k-1]-1]; + INTEGER(f2__)[thislen] = INTEGER_RO(tmp1)[count[k-1]-1]; ++thislen; } else { for (int j=to[i]; j>k; --j) { if (type_count[j-1]) { tmp2 = VECTOR_ELT(type_lookup, j-1); - INTEGER(f2__)[thislen] = INTEGER(tmp2)[0]; // tmp2 will be length 1 + INTEGER(f2__)[thislen] = INTEGER_RO(tmp2)[0]; // tmp2 will be length 1 ++thislen; break; } } if (len == thislen && count[k-1]) { tmp1 = VECTOR_ELT(lookup, k-1); - INTEGER(f2__)[thislen] = INTEGER(tmp1)[count[k-1]-1]; + INTEGER(f2__)[thislen] = INTEGER_RO(tmp1)[count[k-1]-1]; ++thislen; } } @@ -696,18 +696,18 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr if (k > 0) { if (k == to[i] && count[k-1]) { tmp1 = VECTOR_ELT(lookup, k-1); - INTEGER(f2__)[thislen] = INTEGER(tmp1)[count[k-1]-1]; + INTEGER(f2__)[thislen] = INTEGER_RO(tmp1)[count[k-1]-1]; ++thislen; } else if (k < to[i]) { tmp1 = VECTOR_ELT(lookup, k-1); tmp2 = VECTOR_ELT(lookup, to[i]-1); int j=count[k-1]-1, m=count[to[i]-1]-1; while (j>=0 && m>=0) { - if ( INTEGER(tmp1)[j] == INTEGER(tmp2)[m] ) { - INTEGER(f2__)[thislen] = INTEGER(tmp1)[j]; + if ( INTEGER_RO(tmp1)[j] == INTEGER_RO(tmp2)[m] ) { + INTEGER(f2__)[thislen] = INTEGER_RO(tmp1)[j]; ++thislen; --j; --m; break; - } else if ( INTEGER(tmp1)[j] < INTEGER(tmp2)[m] ) { + } else if ( INTEGER_RO(tmp1)[j] < INTEGER_RO(tmp2)[m] ) { --m; } else --j; } @@ -725,7 +725,7 @@ SEXP overlaps(SEXP ux, SEXP imatches, SEXP multArg, SEXP typeArg, SEXP nomatchAr default: internal_error(__func__, "unknown mult: %d", mult); // # nocov } end2 = clock() - start; - if (LOGICAL(verbose)[0]) + if (LOGICAL_RO(verbose)[0]) Rprintf(_("Final step, fetching indices in overlaps ... done in %8.3f seconds\n"), 1.0*(end2)/CLOCKS_PER_SEC); UNPROTECT(1); return(ans); diff --git a/src/init.c b/src/init.c index ef81a7a0e..96a05ff98 100644 --- a/src/init.c +++ b/src/init.c @@ -339,9 +339,9 @@ inline double LLtoD(long long x) { int GetVerbose(void) { // don't call repetitively; save first in that case SEXP opt = GetOption1(sym_verbose); - if ((!isLogical(opt) && !isInteger(opt)) || LENGTH(opt)!=1 || INTEGER(opt)[0]==NA_INTEGER) + if ((!isLogical(opt) && !isInteger(opt)) || LENGTH(opt)!=1 || INTEGER_RO(opt)[0]==NA_INTEGER) error(_("verbose option must be length 1 non-NA logical or integer")); - return INTEGER(opt)[0]; + return INTEGER_RO(opt)[0]; } // # nocov start diff --git a/src/mergelist.c b/src/mergelist.c index 51f28d224..8b16ba191 100644 --- a/src/mergelist.c +++ b/src/mergelist.c @@ -7,7 +7,7 @@ SEXP copyCols(SEXP x, SEXP cols) { internal_error(__func__, "'x' must be a data.table"); // # nocov if (!isInteger(cols)) internal_error(__func__, "'cols' must be integer"); // # nocov - int nx = length(x), ncols = LENGTH(cols), *colsp = INTEGER(cols); + const int nx = length(x), ncols = LENGTH(cols), *colsp = INTEGER_RO(cols); if (!nx || !ncols) return R_NilValue; for (int i=0; i=1")); - DTthrottle = INTEGER(throttle)[0]; + DTthrottle = INTEGER_RO(throttle)[0]; } int old = DTthreads; if (!length(threads) && !length(throttle)) { @@ -138,11 +138,11 @@ SEXP setDTthreads(SEXP threads, SEXP restore_after_fork, SEXP percent, SEXP thro // reflect that and a call to setDTthreads(threads=NULL) will update DTthreads. } else if (length(threads)) { int n = 0; - if (length(threads) != 1 || !isInteger(threads) || (n = INTEGER(threads)[0]) < 0) { // <0 catches NA too since NA is negative (INT_MIN) + if (length(threads) != 1 || !isInteger(threads) || (n = INTEGER_RO(threads)[0]) < 0) { // <0 catches NA too since NA is negative (INT_MIN) error(_("threads= must be either NULL or a single number >= 0. See ?setDTthreads.")); } int num_procs = imax(omp_get_num_procs(), 1); // max just in case omp_get_num_procs() returns <= 0 (perhaps error, or unsupported) - if (!isLogical(percent) || length(percent) != 1 || LOGICAL(percent)[0] == NA_LOGICAL) { + if (!isLogical(percent) || length(percent) != 1 || LOGICAL_RO(percent)[0] == NA_LOGICAL) { internal_error(__func__, "percent= must be TRUE or FALSE at C level"); // # nocov } if (LOGICAL(percent)[0]) { diff --git a/src/shellsort.c b/src/shellsort.c index 47a4fcf41..2c7fe50d1 100644 --- a/src/shellsort.c +++ b/src/shellsort.c @@ -12,17 +12,20 @@ ciura2001 = function(k) if (k==1) 1 else if (k==2) 4 else if (k==3) 10 else if ( # Lee 2021 lee = function(k, y=2.243609061420001) tokuda(k, y=y) */ -static const int sedgewick1982[17] = { - 1073790977, 268460033, 67121153, 16783361, 4197377, 1050113, - 262913, 65921, 16577, 4193, 1073, 281, 77, 23, 8, 1, 0 -}; -#define NGAPS 16 /* shellsort * uses sedgewick1982 gap sequence formula as it turned out to be the most efficient - tested various n, k (for rnorm only!) * currently used in frollmedian algo="fast" when no NAs */ void shellsort(const double *x, int n, int *o) { + + static const int sedgewick1982[17] = { + 1073790977, 268460033, 67121153, 16783361, 4197377, 1050113, + 262913, 65921, 16577, 4193, 1073, 281, 77, 23, 8, 1, 0 + }; + + static const int NGAPS = 16; + for (int i=0; i < n; i++) o[i] = i; int gap = 0; while (sedgewick1982[gap] > n) gap++; diff --git a/src/shift.c b/src/shift.c index 1ddc3549b..62e29e3a9 100644 --- a/src/shift.c +++ b/src/shift.c @@ -30,7 +30,7 @@ SEXP shift(SEXP obj, SEXP k, SEXP fill, SEXP type) int nx = length(x), nk = length(k); if (!isInteger(k)) internal_error(__func__, "k must be integer"); // # nocov - const int *kd = INTEGER(k); + const int *kd = INTEGER_RO(k); for (int i=0; i= 0) || (stype == LEAD && kd[j] < 0)) { // LAG when type %in% c('lag','cyclic') and n >= 0 _or_ type = 'lead' and n < 0 if (tailk > 0) memmove(itmp+thisk, ielem, tailk*size); @@ -75,11 +75,11 @@ SEXP shift(SEXP obj, SEXP k, SEXP fill, SEXP type) } } break; case REALSXP : { - const double dfill = REAL(thisfill)[0]; + const double dfill = REAL_RO(thisfill)[0]; for (int j=0; j= 0.", max); // # nocov includes NA which will print as INT_MIN - if (!isLogical(allowNAArg) || LENGTH(allowNAArg)!=1 || LOGICAL(allowNAArg)[0]==NA_LOGICAL) + if (!isLogical(allowNAArg) || LENGTH(allowNAArg)!=1 || LOGICAL_RO(allowNAArg)[0]==NA_LOGICAL) internal_error(__func__, "allowNAArg must be TRUE/FALSE"); // # nocov - const bool allowNA = LOGICAL(allowNAArg)[0]; + const bool allowNA = LOGICAL_RO(allowNAArg)[0]; - const int *idxp = INTEGER(idx); + const int *idxp = INTEGER_RO(idx); bool stop = false; #pragma omp parallel for num_threads(getDTthreads(n, true)) for (int i=0; iLENGTH(x)) error(_("Item %d of cols is %d which is outside the range [1,ncol(x)=%d]"), i+1, this, LENGTH(x)); + if (this[i]<1 || this[i]>LENGTH(x)) error(_("Item %d of cols is %d which is outside the range [1,ncol(x)=%d]"), i+1, this[i], LENGTH(x)); } int overAlloc = checkOverAlloc(GetOption1(install("datatable.alloccol"))); @@ -310,7 +311,7 @@ SEXP subsetDT(SEXP x, SEXP rows, SEXP cols) { // API change needs update NEWS.md int ansn; if (isNull(rows)) { ansn = nrow; - const int *colD = INTEGER(cols); + const int *colD = INTEGER_RO(cols); for (int i=0; i