|
6 | 6 | - The replacement of NAs with non-NA values from subsequent vectors |
7 | 7 | - The conditional checks within parallelized loops |
8 | 8 | */ |
9 | | -SEXP coalesce(SEXP x, SEXP inplaceArg) { |
| 9 | +SEXP coalesce(SEXP x, SEXP inplaceArg, SEXP nan_is_na_arg) { |
10 | 10 | if (TYPEOF(x)!=VECSXP) internal_error(__func__, "input is list(...) at R level"); // # nocov |
11 | 11 | if (!IS_TRUE_OR_FALSE(inplaceArg)) internal_error(__func__, "argument 'inplaceArg' must be TRUE or FALSE"); // # nocov |
| 12 | + if (!IS_TRUE_OR_FALSE(nan_is_na_arg)) internal_error(__func__, "argument 'nan_is_na_arg' must be TRUE or FALSE"); // # nocov |
12 | 13 | const bool inplace = LOGICAL(inplaceArg)[0]; |
| 14 | + const bool nan_is_na = LOGICAL(nan_is_na_arg)[0]; |
13 | 15 | const bool verbose = GetVerbose(); |
14 | 16 | int nprotect = 0; |
15 | 17 | if (length(x)==0 || isNull(VECTOR_ELT(x,0))) return R_NilValue; // coalesce(NULL, "foo") return NULL even though character type mismatches type NULL |
@@ -102,23 +104,44 @@ SEXP coalesce(SEXP x, SEXP inplaceArg) { |
102 | 104 | } else { |
103 | 105 | double *xP = REAL(first), finalVal=NA_REAL; |
104 | 106 | int k=0; |
105 | | - for (int j=0; j<nval; ++j) { |
106 | | - SEXP item = VECTOR_ELT(x, j+off); |
107 | | - if (length(item)==1) { |
108 | | - double tt = REAL(item)[0]; |
109 | | - if (ISNAN(tt)) continue; |
110 | | - finalVal = tt; |
111 | | - break; |
| 107 | + if (nan_is_na) { |
| 108 | + for (int j=0; j<nval; ++j) { |
| 109 | + SEXP item = VECTOR_ELT(x, j+off); |
| 110 | + if (length(item)==1) { |
| 111 | + double tt = REAL(item)[0]; |
| 112 | + if (ISNAN(tt)) continue; |
| 113 | + finalVal = tt; |
| 114 | + break; |
| 115 | + } |
| 116 | + valP[k++] = REAL_RO(item); |
| 117 | + } |
| 118 | + const bool final = !ISNAN(finalVal); |
| 119 | + #pragma omp parallel for num_threads(getDTthreads(nrow, true)) |
| 120 | + for (int i=0; i<nrow; ++i) { |
| 121 | + double val=xP[i]; |
| 122 | + if (!ISNAN(val)) continue; |
| 123 | + int j=0; while (ISNAN(val) && j<k) val=((double *)valP[j++])[i]; |
| 124 | + if (!ISNAN(val)) xP[i]=val; else if (final) xP[i]=finalVal; |
| 125 | + } |
| 126 | + } else { |
| 127 | + for (int j=0; j<nval; ++j) { |
| 128 | + SEXP item = VECTOR_ELT(x, j+off); |
| 129 | + if (length(item)==1) { |
| 130 | + double tt = REAL(item)[0]; |
| 131 | + if (ISNA(tt)) continue; |
| 132 | + finalVal = tt; |
| 133 | + break; |
| 134 | + } |
| 135 | + valP[k++] = REAL_RO(item); |
| 136 | + } |
| 137 | + const bool final = !ISNA(finalVal); |
| 138 | + #pragma omp parallel for num_threads(getDTthreads(nrow, true)) |
| 139 | + for (int i=0; i<nrow; ++i) { |
| 140 | + double val=xP[i]; |
| 141 | + if (!ISNA(val)) continue; |
| 142 | + int j=0; while (ISNA(val) && j<k) val=((double *)valP[j++])[i]; |
| 143 | + if (!ISNA(val)) xP[i]=val; else if (final) xP[i]=finalVal; |
112 | 144 | } |
113 | | - valP[k++] = REAL_RO(item); |
114 | | - } |
115 | | - const bool final = !ISNAN(finalVal); |
116 | | - #pragma omp parallel for num_threads(getDTthreads(nrow, true)) |
117 | | - for (int i=0; i<nrow; ++i) { |
118 | | - double val=xP[i]; |
119 | | - if (!ISNAN(val)) continue; |
120 | | - int j=0; while (ISNAN(val) && j<k) val=((double *)valP[j++])[i]; |
121 | | - if (!ISNAN(val)) xP[i]=val; else if (final) xP[i]=finalVal; |
122 | 145 | } |
123 | 146 | } |
124 | 147 | } break; |
|
0 commit comments