Skip to content

Commit 9aca06d

Browse files
committed
Keep size floor division in the real domain
1 parent 6e92398 commit 9aca06d

2 files changed

Lines changed: 42 additions & 2 deletions

File tree

R/manifest.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ dims2f_eval_base_env[["%/%"]] <- function(e1, e2) {
510510
quotient <- glue(
511511
"(real({e1}, kind=c_double) / real({e2}, kind=c_double))"
512512
)
513-
glue("floor({quotient}, kind=c_ptrdiff_t)")
513+
real_floor_expr(quotient)
514514
}
515515
dims2f_eval_base_env[["%%"]] <- function(e1, e2) {
516516
glue(

tests/testthat/test-sizes-arithmetic.R

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ test_that("size integer division evaluates numeric operands before casting", {
6969
}
7070

7171
code <- suppressWarnings(r2f(fn))
72-
expect_match(as.character(code), "floor(", fixed = TRUE)
72+
expect_match(as.character(code), "aint(", fixed = TRUE)
7373
expect_match(as.character(code), "real(x, kind=c_double)", fixed = TRUE)
7474
expect_match(as.character(code), "real(y, kind=c_double)", fixed = TRUE)
7575
expect_match(code@c_bridge, "floor(", fixed = TRUE)
@@ -89,6 +89,46 @@ test_that("size integer division rounds negative quotients down", {
8989
expect_quick_identical(fn, list(-3L, 2L))
9090
})
9191

92+
test_that("size floor division remains real before outer arithmetic", {
93+
fn <- function(x, y, z) {
94+
declare(
95+
type(x = double(1)),
96+
type(y = double(1)),
97+
type(z = double(1))
98+
)
99+
out <- double(1)
100+
local <- double(as.integer((x %/% y) / z) + 10L)
101+
out[1] <- as.double(length(local))
102+
out
103+
}
104+
105+
code <- r2f(fn)
106+
expect_match(as.character(code), "aint(", fixed = TRUE)
107+
expect_quick_identical(
108+
fn,
109+
list(1e20, 3, 1e19),
110+
list(-1e20, 3, 1e19)
111+
)
112+
113+
returned <- function(x, y, z) {
114+
declare(
115+
type(x = double(1)),
116+
type(y = double(1)),
117+
type(z = double(1))
118+
)
119+
out <- double(as.integer((x %/% y) / z) + 10L)
120+
for (i in seq_len(length(out))) {
121+
out[i] <- as.double(i)
122+
}
123+
out
124+
}
125+
expect_quick_identical(
126+
returned,
127+
list(1e20, 3, 1e19),
128+
list(-1e20, 3, 1e19)
129+
)
130+
})
131+
92132
test_that("size modulo uses the divisor's sign", {
93133
fn <- function(x, y) {
94134
declare(type(x = integer(1)), type(y = integer(1)))

0 commit comments

Comments
 (0)