From 738d48ceaac4e7dea119a8b15ec3d803c0ff0c3a Mon Sep 17 00:00:00 2001 From: Ivan K Date: Thu, 26 Dec 2024 18:37:11 +0300 Subject: [PATCH] anySpecialStatic(): hash instead of TRUELENGTH --- src/dogroups.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/dogroups.c b/src/dogroups.c index cc7554c3e..f5f590742 100644 --- a/src/dogroups.c +++ b/src/dogroups.c @@ -3,7 +3,7 @@ #include #include -static bool anySpecialStatic(SEXP x) { +static bool anySpecialStatic(SEXP x, hashtab * specials) { // Special refers to special symbols .BY, .I, .N, and .GRP; see special-symbols.Rd // Static because these are like C static arrays which are the same memory for each group; e.g., dogroups // creates .SD for the largest group once up front, overwriting the contents for each group. Their @@ -46,16 +46,16 @@ static bool anySpecialStatic(SEXP x) { if (n==0) return false; if (isVectorAtomic(x)) - return ALTREP(x) || TRUELENGTH(x)<0; + return ALTREP(x) || hash_lookup(specials, x, 0)<0; if (isNewList(x)) { - if (TRUELENGTH(x)<0) + if (hash_lookup(specials, x, 0)<0) return true; // test 2158 for (int i=0; i maxGrpSize) maxGrpSize = ilens[i]; } defineVar(install(".I"), I = PROTECT(allocVector(INTSXP, maxGrpSize)), env); nprotect++; - SET_TRUELENGTH(I, -maxGrpSize); // marker for anySpecialStatic(); see its comments + hash_set(specials, I, -maxGrpSize); // marker for anySpecialStatic(); see its comments R_LockBinding(install(".I"), env); SEXP dtnames = PROTECT(getAttrib(dt, R_NamesSymbol)); nprotect++; // added here to fix #91 - `:=` did not issue recycling warning during "by" @@ -149,7 +150,7 @@ SEXP dogroups(SEXP dt, SEXP dtcols, SEXP groups, SEXP grpcols, SEXP jiscols, SEX 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 - SET_TRUELENGTH(this, -maxGrpSize); // marker for anySpecialStatic(); see its comments + hash_set(specials, this, -maxGrpSize); // marker for anySpecialStatic(); see its comments } SEXP xknames = PROTECT(getAttrib(xSD, R_NamesSymbol)); nprotect++; @@ -328,7 +329,7 @@ SEXP dogroups(SEXP dt, SEXP dtcols, SEXP groups, SEXP grpcols, SEXP jiscols, SEX copyMostAttrib(RHS, target); // attributes of first group dominate; e.g. initial factor levels come from first group } bool copied = false; - if (isNewList(target) && anySpecialStatic(RHS)) { // see comments in anySpecialStatic() + if (isNewList(target) && anySpecialStatic(RHS, specials)) { // see comments in anySpecialStatic() RHS = PROTECT(copyAsPlain(RHS)); copied = true; } @@ -434,7 +435,7 @@ SEXP dogroups(SEXP dt, SEXP dtcols, SEXP groups, SEXP grpcols, SEXP jiscols, SEX error(_("Supplied %d items for column %d of group %d which has %d rows. 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."), thislen, j+1, i+1, maxn); } bool copied = false; - if (isNewList(target) && anySpecialStatic(source)) { // see comments in anySpecialStatic() + if (isNewList(target) && anySpecialStatic(source, specials)) { // see comments in anySpecialStatic() source = PROTECT(copyAsPlain(source)); copied = true; } @@ -484,12 +485,6 @@ SEXP dogroups(SEXP dt, SEXP dtcols, SEXP groups, SEXP grpcols, SEXP jiscols, SEX } SETLENGTH(I, maxGrpSize); SET_TRUELENGTH(I, maxGrpSize); - for (int i=0; i0;