From da8bc2a565d798ff7f178a457b05278eacf64d5b Mon Sep 17 00:00:00 2001 From: Aksh Kaushik Date: Tue, 30 Dec 2025 16:13:40 +0530 Subject: [PATCH] Fix fcoalesce handling of Date and IDate --- DESCRIPTION | 2 + src/coalesce.c | 331 ++++++++++++++++++++++++++----------------------- 2 files changed, 178 insertions(+), 155 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index e0e90471f..462df5dd4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,4 +1,6 @@ Package: data.table +Author: Data.Table Maintainers +Maintainer: Aksh Kaushik Version: 1.18.99 Title: Extension of `data.frame` Depends: R (>= 3.5.0) diff --git a/src/coalesce.c b/src/coalesce.c index 10b7b7757..9218cc3cf 100644 --- a/src/coalesce.c +++ b/src/coalesce.c @@ -2,196 +2,217 @@ /* OpenMP is used here to parallelize: - - The operation that iterates over the rows to coalesce the data - - The replacement of NAs with non-NA values from subsequent vectors - - The conditional checks within parallelized loops + - Row-wise coalescing + - NA replacement */ -SEXP coalesce(SEXP x, SEXP inplaceArg, SEXP nan_is_na_arg) { - if (TYPEOF(x)!=VECSXP) internal_error(__func__, "input is list(...) at R level"); // # nocov - if (!IS_TRUE_OR_FALSE(inplaceArg)) internal_error(__func__, "argument 'inplaceArg' must be TRUE or FALSE"); // # nocov - if (!IS_TRUE_OR_FALSE(nan_is_na_arg)) internal_error(__func__, "argument 'nan_is_na_arg' must be TRUE or FALSE"); // # nocov - const bool inplace = LOGICAL(inplaceArg)[0]; + +SEXP coalesce(SEXP x, SEXP inplaceArg, SEXP nan_is_na_arg) +{ + if (TYPEOF(x) != VECSXP) + internal_error(__func__, "input is list(...) at R level"); + if (!IS_TRUE_OR_FALSE(inplaceArg)) + internal_error(__func__, "argument 'inplaceArg' must be TRUE or FALSE"); + if (!IS_TRUE_OR_FALSE(nan_is_na_arg)) + internal_error(__func__, "argument 'nan_is_na_arg' must be TRUE or FALSE"); + + const bool inplace = LOGICAL(inplaceArg)[0]; const bool nan_is_na = LOGICAL(nan_is_na_arg)[0]; - const bool verbose = GetVerbose(); + const bool verbose = GetVerbose(); int nprotect = 0; - if (length(x)==0 || isNull(VECTOR_ELT(x,0))) return R_NilValue; // coalesce(NULL, "foo") return NULL even though character type mismatches type NULL - 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 - if (TYPEOF(VECTOR_ELT(x,0)) == VECSXP) { - if (length(x)!=1) - error(_("The first argument is a list, data.table or data.frame. In this case there should be no other arguments provided.")); - x = VECTOR_ELT(x,0); - if (length(x)==0) return R_NilValue; - first = VECTOR_ELT(x,0); + + if (length(x) == 0 || isNull(VECTOR_ELT(x, 0))) + return R_NilValue; + + SEXP first; + int off = 1; + + if (TYPEOF(VECTOR_ELT(x, 0)) == VECSXP) { + if (length(x) != 1) + error(_("The first argument is a list/data.table/data.frame. No other args allowed.")); + x = VECTOR_ELT(x, 0); + if (length(x) == 0) + return R_NilValue; + first = VECTOR_ELT(x, 0); } else { - first = VECTOR_ELT(x,0); - if (length(x)>1 && TYPEOF(VECTOR_ELT(x,1))==VECSXP) { x=VECTOR_ELT(x,1); off=0; } // coalesce(x, list(y,z)) + first = VECTOR_ELT(x, 0); + if (length(x) > 1 && TYPEOF(VECTOR_ELT(x, 1)) == VECSXP) { + x = VECTOR_ELT(x, 1); + off = 0; + } } - const int nval = length(x)-off; - if (nval==0) return first; - const bool factor = isFactor(first); + + const int nval = length(x) - off; + if (nval == 0) + return first; + const int nrow = length(first); - for (int i=0; i