skip_on_cran() test_that("rev() reverses vectors", { fn_dbl <- function(x) { declare(type(x = double(NA))) rev(x) } expect_quick_identical( fn_dbl, list(as.double(1:5)), list(as.double(c(2, -1, 3, 0))) ) fn_int <- function(x) { declare(type(x = integer(NA))) rev(x) } expect_quick_identical(fn_int, list(as.integer(c(1, 0, -3, 2)))) # Logical arguments are passed via the bind(c) interface as integer storage. fn_lgl <- function(x) { declare(type(x = logical(NA))) rev(x) } expect_quick_identical(fn_lgl, list(c(TRUE, FALSE, TRUE, FALSE))) expect_quick_identical(fn_lgl, list(c(TRUE, NA, FALSE, TRUE))) }) test_that("rev() preserves bind(c) logical scalar storage (incl. NA)", { fn <- function(m) { declare(type(m = logical(1))) rev(m) } expect_quick_identical(fn, list(TRUE)) expect_quick_identical(fn, list(FALSE)) expect_quick_identical(fn, list(NA)) }) test_that("rev(rev()) preserves bind(c) logical storage (incl. NA)", { fn <- function(m) { declare(type(m = logical(NA))) rev(rev(m)) } m <- c(TRUE, FALSE, NA, TRUE, FALSE) expect_quick_identical(fn, list(m)) }) test_that("rev() result can flow into logical coercions and reductions", { fn_as_integer <- function(m) { declare(type(m = logical(NA))) as.integer(rev(m)) } fn_which_max <- function(m) { declare(type(m = logical(NA))) which.max(rev(m)) } fn_which_min <- function(m) { declare(type(m = logical(NA))) which.min(rev(m)) } m <- c(TRUE, FALSE, TRUE, FALSE, TRUE, TRUE) expect_quick_identical(fn_as_integer, list(m)) expect_quick_identical(fn_which_max, list(m)) expect_quick_identical(fn_which_min, list(m)) }) test_that("rev() works inside compound logical expressions", { fn <- function(x) { declare(type(x = logical(NA))) out <- ifelse(rev(x) & x, 1L, 0L) out } x <- c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) expect_quick_identical(fn, list(x)) }) test_that("rev() works as an external logical mask in x[mask]", { fn <- function(x, m) { declare({ type(x = double(NA)) type(m = logical(NA)) }) sum(x[rev(m)]) } x <- as.double(seq_len(10)) m <- c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE) expect_quick_equal(fn, list(x, m)) }) test_that("rev() mask assignment preserves bind(c) storage through local symbols", { fn <- function(x, m) { declare({ type(x = double(NA)) type(m = logical(NA)) }) r <- rev(m) sum(x[r]) } x <- as.double(seq_len(12)) m <- c( TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE ) expect_quick_equal(fn, list(x, m)) }) test_that("rev() works on local Fortran logical vectors and masks", { fn <- function(x) { declare(type(x = double(NA))) m <- x > 0 sum(x[rev(m)]) } x <- as.double(c(-2, -1, 0, 1, 2, 3, -4, 5)) expect_quick_equal(fn, list(x)) }) test_that("rev() can be used as a reduction mask (sum(x[mask]))", { fn <- function(x, m) { declare({ type(x = double(NA)) type(m = logical(NA)) }) sum(x[rev(m)]) } x <- as.double(seq_len(20)) m <- rep(c(TRUE, FALSE, TRUE, TRUE), length.out = length(x)) expect_quick_equal(fn, list(x, m)) }) test_that("rev() hoists array expressions", { fn <- function(x) { declare(type(x = double(NA))) rev(x + 1) } expect_quick_identical(fn, list(as.double(1:6))) }) test_that("rev() is a no-op for scalars", { fn <- function(x) { declare(type(x = double(1))) rev(x) } expect_quick_identical(fn, list(as.double(3))) })