Skip to content

Commit 064387a

Browse files
authored
Merge branch 'master' into ReformattingAndCleanup
2 parents 84a3279 + b3a1134 commit 064387a

File tree

8 files changed

+37
-21
lines changed

8 files changed

+37
-21
lines changed

NEWS.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,21 +122,21 @@
122122
123123
5. A GitHub Actions workflow is now in place to warn the entire maintainer team, as well as any contributor following the GitHub repository, when the package is at risk of archival on CRAN [#7008](https://github.com/Rdatatable/data.table/issues/7008). Thanks @tdhock for the original report and @Bisaloo and @TysonStanley for the fix.
124124
125-
# data.table [v1.17.8](https://github.com/Rdatatable/data.table/milestone/41) (6 July 2025)
125+
## data.table [v1.17.8](https://github.com/Rdatatable/data.table/milestone/41) (6 July 2025)
126126
127127
1. Internal functions used to signal errors are now marked as non-returning, silencing a compiler warning about potentially unchecked allocation failure. Thanks to Prof. Brian D. Ripley for the report and @aitap for the fix, [#7070](https://github.com/Rdatatable/data.table/pull/7070).
128128
129-
# data.table [v1.17.6](https://github.com/Rdatatable/data.table/milestone/40) (15 June 2025)
129+
## data.table [v1.17.6](https://github.com/Rdatatable/data.table/milestone/40) (15 June 2025)
130130
131131
1. On a heavily loaded machine, a `forder` thread could try to perform a zero-length copy from a null pointer, which was de-facto harmless but is against the C standard and was caught by additional CRAN checks, [#7051](https://github.com/Rdatatable/data.table/issues/7051). Thanks to @helske for the report and @aitap for the PR.
132132
133-
# data.table [v1.17.4](https://github.com/Rdatatable/data.table/milestone/39) (25 May 2025)
133+
## data.table [v1.17.4](https://github.com/Rdatatable/data.table/milestone/39) (25 May 2025)
134134
135135
1. The C code now avoids passing invalid data pointers from 0-length vectors to `memcpy()`, which previously caused undefined behaviour. Thanks to Prof. Brian D. Ripley for the report and Michael Chirico for the fix, [#6911](https://github.com/Rdatatable/data.table/pull/6911).
136136
137-
# data.table [v1.17.2](https://github.com/Rdatatable/data.table/milestone/38) (7 May 2025)
137+
## data.table [v1.17.2](https://github.com/Rdatatable/data.table/milestone/38) (7 May 2025)
138138
139-
## BUG FIXES
139+
### BUG FIXES
140140
141141
1. `fwrite(compress="gzip")` once again produces a gzip header when the column names are missing or disabled, [@6852](https://github.com/Rdatatable/data.table/issues/6852). Thanks @maxscheiber for the report and @aitap for the fix.
142142
@@ -152,7 +152,7 @@
152152
153153
7. `as.data.table()` now properly handles keys: specifying keys sets them, omitting keys preserves existing ones, and setting `key=NULL` clears them, [#6859](https://github.com/Rdatatable/data.table/issues/6859). Thanks @brookslogan for the report and @Mukulyadav2004 for the fix.
154154
155-
## NOTES
155+
### NOTES
156156
157157
1. Continued work to remove non-API C functions, [#6180](https://github.com/Rdatatable/data.table/issues/6180). Thanks Ivan Krylov for the PRs and for writing a clear and concise guide about the R API: https://aitap.codeberg.page/R-api/.
158158

R/between.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ between = function(x, lower, upper, incbounds=TRUE, NAbounds=TRUE, check=FALSE,
3030
}
3131
if (is.i64(x)) {
3232
if (!requireNamespace("bit64", quietly=TRUE)) stopf("trying to use integer64 class when 'bit64' package is not installed") # nocov
33-
if (!is.i64(lower) && is.numeric(lower)) lower = bit64::as.integer64(lower)
34-
if (!is.i64(upper) && is.numeric(upper)) upper = bit64::as.integer64(upper)
33+
if (!is.i64(lower) && (is.integer(lower) || fitsInInt64(lower))) lower = bit64::as.integer64(lower)
34+
if (!is.i64(upper) && (is.integer(upper) || fitsInInt64(upper))) upper = bit64::as.integer64(upper)
3535
}
3636
is.supported = function(x) is.numeric(x) || is.character(x) || is.px(x)
3737
if (is.supported(x) && is.supported(lower) && is.supported(upper)) {

inst/tests/tests.Rraw

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15068,7 +15068,7 @@ if (test_bit64) {
1506815068
as.i64 = bit64::as.integer64
1506915069
test(2039.01, between(1:10, as.i64(3), as.i64(6)), error="x is not integer64 but.*Please align classes")
1507015070
test(2039.02, between(1:10, 3, as.i64(6)), error="x is not integer64 but.*Please align classes")
15071-
test(2039.03, between(as.i64(1:3), "2", as.i64(4)), error="x is integer64 but lower and/or upper are not")
15071+
test(2039.03, between(as.i64(1:3), "2", as.i64(4)), error="x is integer64 but lower is not.*Please align classes")
1507215072
old = options("datatable.verbose"=TRUE)
1507315073
x = as.i64(1:10)
1507415074
ans36 = c(FALSE,FALSE,TRUE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE)
@@ -15095,6 +15095,10 @@ if (test_bit64) {
1509515095
test(2039.19, between(x+maxint, 3+maxint, NA, incbounds=FALSE), c(head(ans36open, -5L), rep(TRUE, 5)), output="between parallel processing of integer64 took")
1509615096
test(2039.20, between(x+maxint, rep(NA, 10L), rep(6+maxint, 10L)), c(TRUE, TRUE, tail(ans36, -2L)), output="between parallel processing of integer64 took")
1509715097
test(2039.21, between(x+maxint, rep(3+maxint, 10L), rep(NA, 10L), incbounds=FALSE), c(head(ans36open, -5L), rep(TRUE, 5)), output="between parallel processing of integer64 took")
15098+
# must not blindly read integer64 values as doubles when the latter fit into int32, #7164
15099+
test(2039.22, between(42L, structure(41., class="integer64"), structure(43., class="integer64")), error="x is not integer64 but.*Please align classes")
15100+
# must not blindly convert numeric bounds to integer64, #7164
15101+
test(2039.23, between(as.i64(42), 41, -2^98), error="x is integer64 but upper is not.*Please align classes")
1509815102
options(old)
1509915103
}
1510015104

src/between.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAboundsArg, S
2929
const bool check = LOGICAL(checkArg)[0];
3030
const bool verbose = GetVerbose();
3131

32+
// check before potential coercion which ignores methods, #7164
33+
if (INHERITS(x, char_integer64)) {
34+
if (!INHERITS(lower, char_integer64))
35+
error(_("x is integer64 but %s is not. Please align classes."), "lower"); // e.g. between(int64, character, character)
36+
if (!INHERITS(upper, char_integer64))
37+
error(_("x is integer64 but %s is not. Please align classes."), "upper"); // e.g. between(int64, character, character)
38+
} else {
39+
if (INHERITS(lower, char_integer64))
40+
error(_("x is not integer64 but %s is. Please align classes."), "lower");
41+
if (INHERITS(upper, char_integer64))
42+
error(_("x is not integer64 but %s is. Please align classes."), "upper");
43+
}
44+
3245
if (isInteger(x)) {
3346
if ((isInteger(lower) || fitsInInt32(lower)) &&
3447
(isInteger(upper) || fitsInInt32(upper))) { // #3517 coerce to num to int when possible
@@ -90,8 +103,6 @@ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAboundsArg, S
90103

91104
case REALSXP:
92105
if (INHERITS(x, char_integer64)) {
93-
if (!INHERITS(lower, char_integer64) || !INHERITS(upper, char_integer64))
94-
error(_("x is integer64 but lower and/or upper are not.")); // e.g. between(int64, character, character)
95106
const int64_t *lp = (int64_t *)REAL(lower);
96107
const int64_t *up = (int64_t *)REAL(upper);
97108
const int64_t *xp = (int64_t *)REAL(x);
@@ -117,8 +128,6 @@ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAboundsArg, S
117128
}
118129
if (verbose) Rprintf(_("between parallel processing of integer64 took %8.3fs\n"), omp_get_wtime()-tic);
119130
} else {
120-
if (INHERITS(lower, char_integer64) || INHERITS(upper, char_integer64))
121-
error(_("x is not integer64 but lower and/or upper is integer64. Please align classes."));
122131
const double *lp = REAL(lower);
123132
const double *up = REAL(upper);
124133
const double *xp = REAL(x);

src/fread.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,10 +927,13 @@ static void parse_double_hexadecimal(FieldParseContext *ctx)
927927
if (neg) ch++;
928928
else if (*ch == '+') ch++;
929929

930-
const bool subnormal = ch[2] == '0';
930+
bool subnormal = false;
931931

932+
// Important!
933+
// Keep in mind that only ch[0] is guaranteed to be mapped.
934+
// Rearranging these checks (e.g. to make 'subnormal' const) will lead to segfaults in rare cases.
932935
if (ch[0] == '0' && (ch[1] == 'x' || ch[1] == 'X') &&
933-
(ch[2] == '1' || (subnormal)) && ch[3] == '.') {
936+
(ch[2] == '1' || (subnormal = (ch[2] == '0'))) && ch[3] == '.') {
934937
ch += 4;
935938
uint64_t acc = 0;
936939
uint8_t digit;

src/utils.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ bool within_int64_repres(double x) {
1414
// used to error if not passed type double but this needed extra is.double() calls in calling R code
1515
// which needed a repeat of the argument. Hence simpler and more robust to return false when not type double.
1616
bool fitsInInt32(SEXP x) {
17-
if (!isReal(x))
17+
if (!isReal(x) || INHERITS(x, char_integer64))
1818
return false;
1919
R_xlen_t n=xlength(x), i=0;
2020
const double *dx = REAL(x);
@@ -31,7 +31,7 @@ SEXP fitsInInt32R(SEXP x) {
3131
}
3232

3333
bool fitsInInt64(SEXP x) {
34-
if (!isReal(x))
34+
if (!isReal(x) || INHERITS(x, char_integer64))
3535
return false;
3636
R_xlen_t n=xlength(x), i=0;
3737
const double *dx = REAL(x);

vignettes/datatable-joins.Rmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ x[i, on, nomatch]
117117
\____ secondary data.table
118118
```
119119

120-
Note: Please keep in mind that the standard argument order in `data.table` is `dt[i, j, by]`. For join operations, it is recommended to pass the `on` and `nomatch` arguments by name to avoid using `j` and `by` when they are not needed.
120+
**Note**: Please keep in mind that the standard argument order in `data.table` is `dt[i, j, by]`. For join operations, it is recommended to pass the `on` and `nomatch` arguments by name to avoid using `j` and `by` when they are not needed.
121121

122122
## 3. Equi joins
123123

@@ -439,7 +439,7 @@ ProductReceived[ProductSales,
439439
allow.cartesian = TRUE]
440440
```
441441

442-
Note: `allow.cartesian` is defaulted to FALSE as this is seldom what the user wants, and such a cross join can lead to a very large number of rows in the result. For example, if Table A has 100 rows and Table B has 50 rows, their Cartesian product would result in 5000 rows (100 * 50). This can quickly become memory-intensive for large datasets.
442+
**Note**: `allow.cartesian` is defaulted to FALSE as this is seldom what the user wants, and such a cross join can lead to a very large number of rows in the result. For example, if Table A has 100 rows and Table B has 50 rows, their Cartesian product would result in 5000 rows (100 * 50). This can quickly become memory-intensive for large datasets.
443443

444444

445445
#### 3.6.1. Selecting one match

vignettes/fr/datatable-joins.Rmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ x[i, on, nomatch]
117117
\____ data.table secondaire
118118
```
119119

120-
Note : n'oubliez pas que l'ordre standard des arguments dans data.table est `dt[i, j, by]`. Pour les opérations de jointure, il est recommandé de passer les arguments `on` et `nomatch` par nom pour éviter d'utiliser `j` et `by` quand ce n'est pas nécessaire.
120+
**Note** : n'oubliez pas que l'ordre standard des arguments dans data.table est `dt[i, j, by]`. Pour les opérations de jointure, il est recommandé de passer les arguments `on` et `nomatch` par nom pour éviter d'utiliser `j` et `by` quand ce n'est pas nécessaire.
121121

122122
## 3. Jointures équilibrées
123123

@@ -439,7 +439,7 @@ ProductReceived[ProductSales,
439439
allow.cartesian = TRUE]
440440
```
441441

442-
Note : `allow.cartesian` vaut par défaut FALSE car c'est ce que l'utilisateur a souhaité, et une telle jointure croisée peut conduire à un très grand nombre de lignes dans le résultat. Par exemple, si Table A possède 100 lignes et Table
442+
**Note** : `allow.cartesian` vaut par défaut FALSE car c'est ce que l'utilisateur a souhaité, et une telle jointure croisée peut conduire à un très grand nombre de lignes dans le résultat. Par exemple, si Table A possède 100 lignes et Table
443443
B en a 50, leur produit cartésien sera de 5000 lignes (100 * 50). Ce qui peut rapidement accroître la mémoire occupée pour de grands ensembles de données.
444444

445445
#### 3.6.1. Selection d'une seule correspondance

0 commit comments

Comments
 (0)