Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 27 additions & 11 deletions inst/tests/tests.Rraw
Original file line number Diff line number Diff line change
Expand Up @@ -13602,7 +13602,6 @@ test(1967.78, x[1:5, sum(v), by = list(i5 = 1:5 %% 2L), verbose = TRUE],

# gforce integer overflow coerce to double
DT = data.table(A=1:5, B=-3i, C=2147483647L)
test(1968.1, DT[, sum(B), by=A%%2L], error="Type 'complex' not supported by GForce sum (gsum). Either add the")
test(1968.2, storage.mode(DT$C), "integer")
test(1968.3, DT[, sum(C), by=A%%2L], data.table(A=c(1L,0L), V1=c(6442450941, 4294967294)),
warning="sum.*integer column.*more than type 'integer' can hold.*coerced to 'numeric'")
Expand Down Expand Up @@ -14257,16 +14256,16 @@ if (test_bit64) {
DT = data.table(id=c(rep(1L,3), rep(2L, 3)), v=bit64::as.integer64(c(1:3, 4L, 5:6)))
test(2019, DT[2:6, sum(v), id], data.table(id=1:2, V1=bit64::as.integer64(c(5L,15L)))) # gather, case of int64 and irows
}
DT = data.table(id = c(1L,1L,2L), v = c(1i, 2i, 3i))
test(2020.01, DT[, min(v), by=id], error="'complex' not supported by GForce min")
test(2020.02, DT[, max(v), by=id], error="'complex' not supported by GForce max")
test(2020.03, DT[, median(v), by=id], error="'complex' not supported by GForce median")
test(2020.04, DT[, head(v, 1), by=id], error="'complex' not supported by GForce head")
test(2020.05, DT[, tail(v, 1), by=id], error="'complex' not supported by GForce tail")
test(2020.06, DT[, v[1], by=id], error="'complex' not supported by GForce subset")
test(2020.07, DT[, sd(v), by=id], error="'complex' not supported by GForce sd")
test(2020.08, DT[, var(v), by=id], error="'complex' not supported by GForce var")
test(2020.09, DT[, prod(v), by=id], error="'complex' not supported by GForce prod")
DT = data.table(id = c(1L,1L,2L), v = as.raw(0:2))
test(2020.01, DT[, min(v), by=id], error="'raw' not supported by GForce min")
test(2020.02, DT[, max(v), by=id], error="'raw' not supported by GForce max")
test(2020.03, DT[, median(v), by=id], error="'raw' not supported by GForce median")
test(2020.04, DT[, head(v, 1), by=id], error="'raw' not supported by GForce head")
test(2020.05, DT[, tail(v, 1), by=id], error="'raw' not supported by GForce tail")
test(2020.06, DT[, v[1], by=id], error="'raw' not supported by GForce subset")
test(2020.07, DT[, sd(v), by=id], error="'raw' not supported by GForce sd")
test(2020.08, DT[, var(v), by=id], error="'raw' not supported by GForce var")
test(2020.09, DT[, prod(v), by=id], error="'raw' not supported by GForce prod")
DT = data.table(id = c(1L,1L,2L,2L), v = c(1L, 2L, NA, NA))
test(2020.10, DT[, median(v), id], data.table(id=1:2, V1=c(1.5, NA))) # median whole group has NAs

Expand Down Expand Up @@ -15298,6 +15297,23 @@ test(2065.6, DT[ , z_sum := base::sum(z), by = .(a, b)][1:3, z_sum],
c(1.8791864549242+0i, 3.17903639358309+0i, -4.18868631527035+0i))
test(2065.7, DT[1L, z_sum := 1i][1L, z_sum], 1i)

# GForce for complex columns, part of #3690
DT = data.table(id=c(1L,1L,2L), v=c(1i, 2i, 3i))
test(2066.01, DT[, min(v), by=id], error="'complex' has no well-defined min")
test(2066.02, DT[, max(v), by=id], error="'complex' has no well-defined max")
test(2066.03, DT[, head(v, 1), by=id], data.table(id=1:2, V1=c(1, 3)*1i))
test(2066.04, DT[, tail(v, 1), by=id], data.table(id=1:2, V1=(2:3)*1i))
test(2066.05, DT[, v[2], by=id], data.table(id = 1:2, V1=c(2i, NA)))
## former test 1968.1
DT = data.table(A=1:5, B=-3i, C=2147483647L)
test(2066.06, DT[, .(sum(B), mean(B)), by=A%%2L], data.table(A=1:0, V1=c(-9i, -6i), V2=-3i))
test(2066.07, DT[2:4, .(sum(B), mean(B)), by=A%%2L], data.table(A=0:1, V1=c(-6i, -3i), V2=-3i))
DT[4, B:=NA]
test(2066.08, DT[, .(sum(B), mean(B)), by=A%%2L], data.table(A=1:0, V1=c(-9i, NA), V2=c(-3i, NA)))
test(2066.09, DT[2:4, .(sum(B), mean(B)), by=A%%2L], data.table(A=0:1, V1=c(NA, -3i), V2=c(NA, -3i)))
test(2066.10, DT[, .(sum(B, na.rm=TRUE), mean(B, na.rm=TRUE)), by=A%%2L], data.table(A=1:0, V1=c(-9i, -3i), V2=-3i))
test(2066.11, DT[2:4, .(sum(B, na.rm=TRUE), mean(B, na.rm=TRUE)), by=A%%2L], data.table(A=0:1, V1=c(-3i, -3i), V2=-3i))


###################################
# Add new tests above this line #
Expand Down
11 changes: 7 additions & 4 deletions src/coalesce.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SEXP coalesce(SEXP x, SEXP inplaceArg) {
error("Internal error in coalesce.c: argument 'inplaceArg' must be TRUE or FALSE"); // # nocov
const bool inplace = LOGICAL(inplaceArg)[0];
const bool verbose = GetVerbose();
int nprotect = 0;
if (length(x)==0) return R_NilValue;
SEXP first; // the first vector (it might be the first argument, or it might be the first column of a data.table|frame
int off = 1; // when x has been pointed to the list of replacement candidates, is the first candidate in position 0 or 1 in the list
Expand All @@ -29,21 +30,23 @@ SEXP coalesce(SEXP x, SEXP inplaceArg) {
if (factor) {
if (!isFactor(item))
error("Item 1 is a factor but item %d is not a factor. When factors are involved, all items must be factor.", i+2);
if (!R_compute_identical(getAttrib(first, R_LevelsSymbol), getAttrib(item, R_LevelsSymbol), 0))
if (!R_compute_identical(PROTECT(getAttrib(first, R_LevelsSymbol)), PROTECT(getAttrib(item, R_LevelsSymbol)), 0))
error("Item %d is a factor but its levels are not identical to the first item's levels.", i+2);
UNPROTECT(2);
} else {
if (isFactor(item))
error("Item %d is a factor but item 1 is not a factor. When factors are involved, all items must be factor.", i+2);
}
if (TYPEOF(first) != TYPEOF(item))
error("Item %d is type %s but the first item is type %s. Please coerce before coalescing.", i+2, type2char(TYPEOF(item)), type2char(TYPEOF(first)));
if (!R_compute_identical(getAttrib(first, R_ClassSymbol), getAttrib(item, R_ClassSymbol), 0))
if (!R_compute_identical(PROTECT(getAttrib(first, R_ClassSymbol)), PROTECT(getAttrib(item, R_ClassSymbol)), 0))
error("Item %d has a different class than item 1.", i+2);
UNPROTECT(2);
if (length(item)!=1 && length(item)!=nrow)
error("Item %d is length %d but the first item is length %d. Only singletons are recycled.", i+2, length(item), nrow);
}
if (!inplace) {
first = PROTECT(duplicate(first));
first = PROTECT(duplicate(first)); nprotect++;
if (verbose) Rprintf("coalesce copied first item (inplace=FALSE)\n");
}
void **valP = (void **)R_alloc(nval, sizeof(void *));
Expand Down Expand Up @@ -140,7 +143,7 @@ SEXP coalesce(SEXP x, SEXP inplaceArg) {
default:
error("Unsupported type: %s", type2char(TYPEOF(first))); // e.g. raw is tested
}
if (!inplace) UNPROTECT(1);
UNPROTECT(nprotect);
return first;
}

Loading