Skip to content

Commit 109160b

Browse files
committed
Grid: symbolic-vector-vs-1x1 cells are runtime guards for every op class
The 02-2 fix routes arithmetic on a 1x1 matrix and a symbolic-length vector through the vector-matrix rule (guard on length 1, 1x1 result) instead of scalarizing at compile time, closing the shape divergence the review found: at runtime length 1, R keeps the 1x1 dims. Encode that in the verdict function, and give sym operands facing a 1x1 partner the conforming length 1 so the ok-path is exercised at the shape the guard admits. The old sym_len = 3 cells never ran the length-1 branch.
1 parent ea91035 commit 109160b

1 file changed

Lines changed: 15 additions & 9 deletions

File tree

tests/testthat/test-conformability-grid.R

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,13 @@ grid_pair_args <- function(
173173
}
174174

175175
# Length a `sym` operand must have to conform with its partner shape.
176+
# For a matrix partner that is the vector-matrix rule's nrow -- including
177+
# the 1x1 matrix, whose symbolic-vector cells guard on length 1.
176178
grid_sym_ok_len <- function(partner) {
177179
p <- grid_shapes[[partner]]
178180
if (p$kind == "vec" && !is.na(p$len)) {
179181
p$len
180-
} else if (p$kind == "mat" && !all(p$dims == 1L)) {
182+
} else if (p$kind == "mat") {
181183
p$dims[1L]
182184
} else {
183185
3L
@@ -285,10 +287,14 @@ make_grid_cell_fn <- function(sa, sb, op, ma, mb) {
285287
# 4. known mismatch (incl. length 0) -> compile error
286288
# 5. not statically decidable (NA dims) -> runtime guard
287289
# One op-class split, mirroring R: *arithmetic* recycles a 1x1 matrix
288-
# against a vector (deprecated in R but still its answer, so quickr
289-
# scalarizes), while comparisons and & | error there -- for those the 1x1
290-
# is an ordinary one-row matrix and the vector-matrix rule applies (the
291-
# runtime-guard flavor is pinned in test-recycling.R).
290+
# against a vector of statically known length != 1 (deprecated in R but
291+
# still its answer, so quickr scalarizes), while comparisons and & | error
292+
# there -- for those the 1x1 is an ordinary one-row matrix and the
293+
# vector-matrix rule applies. A *symbolic* vector length takes the
294+
# vector-matrix rule for every op class: the result's shape depends on the
295+
# runtime length (R keeps the 1x1 dims only for a length-1 vector), so a
296+
# runtime guard requires length 1 and longer vectors error where R would
297+
# recycle (both flavors are pinned in test-recycling.R).
292298

293299
grid_strict_ops <- c("lt", "eq", "and", "or")
294300

@@ -304,17 +310,17 @@ grid_cell_verdict <- function(sa, sb, opname) {
304310
return(ok)
305311
}
306312
if ((is_1x1(A) && B$kind == "vec") || (is_1x1(B) && A$kind == "vec")) {
307-
if (!(opname %in% grid_strict_ops)) {
308-
return(ok) # scalarized 1x1: R's length-1 array recycling
309-
}
310313
vec <- if (A$kind == "vec") A else B
311314
if (is.na(vec$len)) {
312315
return(guard("matrix first dimension"))
313316
}
314317
if (vec$len == 1L) {
315318
return(ok)
316319
}
317-
return(err("matrix first dimension"))
320+
if (opname %in% grid_strict_ops) {
321+
return(err("matrix first dimension"))
322+
}
323+
return(ok) # scalarized 1x1: R's length-1 array recycling
318324
}
319325
if (A$kind == "vec" && B$kind == "vec") {
320326
if (is.na(A$len) || is.na(B$len)) {

0 commit comments

Comments
 (0)