From f52959c9590b0a28d4a3239d43ef037312f0edbd Mon Sep 17 00:00:00 2001 From: perrydv Date: Mon, 26 Oct 2026 13:10:58 -0700 Subject: [PATCH 1/3] Fix handling of scalar vs length-1 vector in modelValues, including for as.matrix column names --- nimbleModel/R/modelValues.R | 23 +++- .../predef/MVBase_nC/MVBase_nC_manifest.txt | 2 +- .../copier_nClass/copier_nClass_manifest.txt | 2 +- .../declFunBase_nClass_manifest.txt | 2 +- .../instr_nClass/instr_nClass_manifest.txt | 2 +- .../multiCopierMV_nClass_manifest.txt | 2 +- .../predef/mCopy_nC/mCopy_nC_manifest.txt | 2 +- .../modelBase_nClass_manifest.txt | 2 +- nimbleModel/tests/testthat/test-modelValues.R | 117 +++++++++++++++--- 9 files changed, 124 insertions(+), 30 deletions(-) diff --git a/nimbleModel/R/modelValues.R b/nimbleModel/R/modelValues.R index 367606b..19380f3 100644 --- a/nimbleModel/R/modelValues.R +++ b/nimbleModel/R/modelValues.R @@ -226,7 +226,9 @@ make_modelValues_nClass <- function(varInfo, if (is.null(defaultSizes)) defaultSizes <- list() for (v in names(varInfo$vars)) { if (is.null(defaultSizes[[v]]) || length(defaultSizes[[v]]) == 0) { - defaultSizes[[v]] <- rep(0, max(varInfo$vars[[v]]$nDim, 1)) + nDim <- varInfo$vars[[v]]$nDim + # Scalars get size 1 so uncompiled rows are numeric(1). C++ ignores sizes for nDim 0. + defaultSizes[[v]] <- if (nDim == 0) 1 else rep(0, nDim) } } @@ -468,10 +470,11 @@ as.list.modelValues <- function(x, varNames, stack = TRUE, flatten = FALSE, iter if (length(varNames)) { ans <- vector("list", length(varNames)) |> setNames(varNames) for (var in varNames) { - res <- as.list(nCompiler::value(x, var)) # converts nList to list; compiled or uncompiled. + nl <- nCompiler::value(x, var) + res <- as.list(nl) # converts nList to list; compiled or uncompiled. if (flatten) { rawDims <- dimOrLength(res[[1]]) - this_colnames <- dims_2_colnames(rawDims, var = var) + this_colnames <- nList_2_colnames(nl, rawDims, var = var) } if (stack) { res <- simplify2array(res, higher = !flatten) @@ -567,6 +570,18 @@ dims_2_colnames <- function(dims, var = "x") { colnames <- paste0(var, "[", dim_strings, "]") } +# Column names for the variable held in nList nl. +# A true scalar (nDim 0) is named by the variable name alone, as in nimble, +# whereas a length-1 vector is named with "[1]". +# R values do not distinguish these cases, so we use the nList's element type. +nList_2_colnames <- function(nl, dims, var) { + if (isTRUE(nl$get_nDim() == 0L)) { + var + } else { + dims_2_colnames(dims, var = var) + } +} + #' @exportS3Method #' @method as.matrix modelValues as.matrix.modelValues <- function(x) { @@ -579,7 +594,7 @@ as.matrix.modelValues <- function(x) { if (length(this_list) == 0) next dim_x <- dimOrLength(this_list[[1]]) tot_len <- prod(dim_x) - this_colnames <- dims_2_colnames(dim_x, var = vn) + this_colnames <- nList_2_colnames(this_list, dim_x, var = vn) # Possibly add check that all elements have the same dim this_matrix <- this_list |> lapply(\(x) { diff --git a/nimbleModel/inst/include/nimbleModel/predef/MVBase_nC/MVBase_nC_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/MVBase_nC/MVBase_nC_manifest.txt index 74bfa0a..b8ae438 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/MVBase_nC/MVBase_nC_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/MVBase_nC/MVBase_nC_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792534431.59537, class = c("POSIXct", +list(saved_at = structure(1792987436.76702, class = c("POSIXct", "POSIXt")), packet_name = "MVBase_nC", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "MVBase_nC_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/copier_nClass/copier_nClass_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/copier_nClass/copier_nClass_manifest.txt index 59e11d6..9c54968 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/copier_nClass/copier_nClass_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/copier_nClass/copier_nClass_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792534392.88472, class = c("POSIXct", +list(saved_at = structure(1792987331.12855, class = c("POSIXct", "POSIXt")), packet_name = "copier_nClass", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "copier_nClass_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/declFunBase_nC/declFunBase_nClass_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/declFunBase_nC/declFunBase_nClass_manifest.txt index a1c1d52..88949af 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/declFunBase_nC/declFunBase_nClass_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/declFunBase_nC/declFunBase_nClass_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792534340.26498, class = c("POSIXct", +list(saved_at = structure(1792987274.70172, class = c("POSIXct", "POSIXt")), packet_name = "declFunBase_nClass", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "declFunBase_nClass_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/instr_nClass/instr_nClass_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/instr_nClass/instr_nClass_manifest.txt index f4599c0..422935e 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/instr_nClass/instr_nClass_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/instr_nClass/instr_nClass_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792534327.40934, class = c("POSIXct", +list(saved_at = structure(1792987228.03338, class = c("POSIXct", "POSIXt")), packet_name = "instr_nClass", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "instr_nClass_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/mCopyMV_nC/multiCopierMV_nClass_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/mCopyMV_nC/multiCopierMV_nClass_manifest.txt index 95b96dd..79442d1 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/mCopyMV_nC/multiCopierMV_nClass_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/mCopyMV_nC/multiCopierMV_nClass_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792534418.86996, class = c("POSIXct", +list(saved_at = structure(1792987409.09837, class = c("POSIXct", "POSIXt")), packet_name = "multiCopierMV_nClass", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "multiCopierMV_nClass_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/mCopy_nC/mCopy_nC_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/mCopy_nC/mCopy_nC_manifest.txt index bd8d233..71a3a57 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/mCopy_nC/mCopy_nC_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/mCopy_nC/mCopy_nC_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792534403.251, class = c("POSIXct", +list(saved_at = structure(1792987367.85232, class = c("POSIXct", "POSIXt")), packet_name = "mCopy_nC", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "mCopy_nC_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/modelBase_nC/modelBase_nClass_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/modelBase_nC/modelBase_nClass_manifest.txt index 501e012..433df2a 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/modelBase_nC/modelBase_nClass_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/modelBase_nC/modelBase_nClass_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792534353.3121, class = c("POSIXct", +list(saved_at = structure(1792987296.24025, class = c("POSIXct", "POSIXt")), packet_name = "modelBase_nClass", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "modelBase_nClass_preamble.cpp", diff --git a/nimbleModel/tests/testthat/test-modelValues.R b/nimbleModel/tests/testthat/test-modelValues.R index d8615e6..23c1624 100644 --- a/nimbleModel/tests/testthat/test-modelValues.R +++ b/nimbleModel/tests/testthat/test-modelValues.R @@ -1,11 +1,20 @@ # library(nCompiler) # library(nimbleModel) -message("Add scalar elements to all modelValues testing cases.") +# Expected result of as.list(mv, iterationAsLastIndex = TRUE) from per-row lists. +# Stacked scalars come back as a 1 x nRow matrix rather than a vector. +stack_expected <- function(x) { + lapply(x, \(v) { + res <- simplify2array(v) + if (is.null(dim(res))) dim(res) <- c(1, length(res)) + res + }) +} test_that("basic modelValues class works", { varInfo <- list( vars = list( + eta = list(name = "eta", nDim = 0), mu = list(name = "mu", nDim = 1), cov = list(name = "cov", nDim = 2) ) @@ -16,16 +25,20 @@ test_that("basic modelValues class works", { # Basic uncompiled uses: expect_equal(obj$mu |> as.list(), list()) - sizes <- list(mu = 2, cov = c(3, 4)) + expect_equal(obj$eta |> as.list(), list()) + expect_equal(obj$get_sizeList()$eta, 1) # default size for a scalar + sizes <- list(eta = 1, mu = 2, cov = c(3, 4)) obj$set_sizeList(sizes) expect_equal(obj$get_sizeList(), sizes) obj$resize(3) + default_eta3 <- rep(list(0), 3) default_mu3 <- rep(list(numeric(2)), 3) default_cov3 <- matrix(0, nrow = 3, ncol = 4) |> list() |> rep(3) expect_equal(obj$mu |> as.list(), default_mu3) expect_equal(obj$cov |> as.list(), default_cov3) + expect_equal(obj$eta |> as.list(), default_eta3) legacy_setting <- getNimbleModelOption("legacy_nimble") on.exit(setNimbleModelOption("legacy_nimble", legacy_setting)) @@ -46,25 +59,32 @@ test_that("basic modelValues class works", { cat("expected warning about wrong number of items to replace:\n") expect_warning(obj["mu"] <- testList) # Warning for wrong length test_muList <- list(c(1, 2), c(3, 4), c(5, 6)) + test_etaList <- list(1.5, 2.5, 3.5) obj["mu"] <- test_muList expect_equal(obj["mu"] |> as.list(), test_muList) obj["mu"] <- default_mu3 # Set for var and row obj["mu", 1] <- c(1, 2) expect_equal(obj["mu", 1], c(1, 2)) + obj["eta", 1] <- 1.5 + expect_equal(obj["eta", 1], 1.5) # Change length using `length<-`, checking for preserved values. obj["mu"] <- test_muList + obj["eta"] <- test_etaList length(obj) <- 2 expect_equal(length(obj), 2) - list_exp2 <- list(mu = test_muList[1:2], cov = default_cov3[1:2]) - list_exp2_stacked <- lapply(list_exp2, simplify2array) + list_exp2 <- list(eta = test_etaList[1:2], mu = test_muList[1:2], cov = default_cov3[1:2]) + list_exp2_stacked <- stack_expected(list_exp2) # list_exp2 <- list_exp2[sort(names(list_exp2))] expect_equal(as.list(obj, stack = FALSE), list_exp2) expect_equal(as.list(obj, iterationAsLastIndex = TRUE), list_exp2_stacked) length(obj) <- 3 - list_exp3 <- list(mu = c(list_exp2$mu, default_mu3[3]), cov = c(list_exp2$cov, default_cov3[3])) - list_exp3_stacked <- lapply(list_exp3, simplify2array) + list_exp3 <- list( + eta = c(list_exp2$eta, default_eta3[3]), + mu = c(list_exp2$mu, default_mu3[3]), cov = c(list_exp2$cov, default_cov3[3]) + ) + list_exp3_stacked <- stack_expected(list_exp3) # list_exp3 <- list_exp3[sort(names(list_exp3))] expect_equal(as.list(obj, stack = FALSE), list_exp3) expect_equal(as.list(obj, iterationAsLastIndex = TRUE), list_exp3_stacked) @@ -105,16 +125,20 @@ test_that("basic modelValues class works", { # Basic compiled uses expect_equal(obj$mu |> as.list(), list()) - sizes <- list(mu = 2, cov = c(3, 4)) + expect_equal(obj$eta |> as.list(), list()) + expect_equal(obj$get_sizeList()$eta, 1) # default size for a scalar + sizes <- list(eta = 1, mu = 2, cov = c(3, 4)) obj$set_sizeList(sizes) expect_equal(obj$get_sizeList(), sizes) obj$resize(3) + default_eta3 <- rep(list(0), 3) default_mu3 <- rep(list(numeric(2)), 3) default_cov3 <- matrix(0, nrow = 3, ncol = 4) |> list() |> rep(3) expect_equal(obj$mu |> as.list(), default_mu3) expect_equal(obj$cov |> as.list(), default_cov3) + expect_equal(obj$eta |> as.list(), default_eta3) # S3 interface, compiled expect_equal(length(obj), 3) @@ -131,24 +155,31 @@ test_that("basic modelValues class works", { cat("expected warning about wrong number of items to replace:\n") expect_warning(obj["mu"] <- testList) # Warning for wrong length test_muList <- list(c(1, 2), c(3, 4), c(5, 6)) + test_etaList <- list(1.5, 2.5, 3.5) obj["mu"] <- test_muList expect_equal(obj["mu"] |> as.list(), test_muList) obj["mu"] <- default_mu3 # Set for var and row obj["mu", 1] <- c(1, 2) expect_equal(obj["mu", 1], c(1, 2)) + obj["eta", 1] <- 1.5 + expect_equal(obj["eta", 1], 1.5) # Change length using `length<-`, checking for preserved values. obj["mu"] <- test_muList + obj["eta"] <- test_etaList length(obj) <- 2 expect_equal(length(obj), 2) - list_exp2 <- list(mu = test_muList[1:2], cov = default_cov3[1:2]) - list_exp2_stacked <- lapply(list_exp2, simplify2array) + list_exp2 <- list(eta = test_etaList[1:2], mu = test_muList[1:2], cov = default_cov3[1:2]) + list_exp2_stacked <- stack_expected(list_exp2) # list_exp2 <- list_exp2[sort(names(list_exp2))] expect_equal(as.list(obj, stack = FALSE), list_exp2) expect_equal(as.list(obj, iterationAsLastIndex = TRUE), list_exp2_stacked) length(obj) <- 3 - list_exp3 <- list(mu = c(list_exp2$mu, default_mu3[3]), cov = c(list_exp2$cov, default_cov3[3])) + list_exp3 <- list( + eta = c(list_exp2$eta, default_eta3[3]), + mu = c(list_exp2$mu, default_mu3[3]), cov = c(list_exp2$cov, default_cov3[3]) + ) # list_exp3 <- list_exp3[sort(names(list_exp3))] expect_equal(as.list(obj, stack = FALSE), list_exp3) @@ -171,12 +202,15 @@ test_that("basic modelValues class works", { # interface does not have active bindings for the derived content like the specific variables expect_true(is.null(obj$mu)) expect_equal(nCompiler::value(obj, "mu") |> as.list(), list()) - sizes <- list(mu = 2, cov = c(3, 4)) + expect_equal(nCompiler::value(obj, "eta") |> as.list(), list()) + expect_equal(nCompiler::method(obj, "get_sizeList")()$eta, 1) # default size for a scalar + sizes <- list(eta = 1, mu = 2, cov = c(3, 4)) nCompiler::method(obj, "set_sizeList")(sizes) expect_equal(nCompiler::method(obj, "get_sizeList")(), sizes) nCompiler::method(obj, "resize")(3) expect_equal(nCompiler::value(obj, "mu") |> as.list(), default_mu3) expect_equal(nCompiler::value(obj, "cov") |> as.list(), default_cov3) + expect_equal(nCompiler::value(obj, "eta") |> as.list(), default_eta3) # In S3 interface use, normal syntax should work # because the S3 interface functions use value() and method() @@ -195,22 +229,29 @@ test_that("basic modelValues class works", { cat("expected warning about wrong number of items to replace:\n") expect_warning(obj["mu"] <- testList) # Warning for wrong length test_muList <- list(c(1, 2), c(3, 4), c(5, 6)) + test_etaList <- list(1.5, 2.5, 3.5) obj["mu"] <- test_muList expect_equal(obj["mu"] |> as.list(), test_muList) obj["mu"] <- default_mu3 # Set for var and row obj["mu", 1] <- c(1, 2) expect_equal(obj["mu", 1], c(1, 2)) + obj["eta", 1] <- 1.5 + expect_equal(obj["eta", 1], 1.5) # Change length using `length<-`, checking for preserved values. obj["mu"] <- test_muList + obj["eta"] <- test_etaList length(obj) <- 2 expect_equal(length(obj), 2) - list_exp2 <- list(mu = test_muList[1:2], cov = default_cov3[1:2]) + list_exp2 <- list(eta = test_etaList[1:2], mu = test_muList[1:2], cov = default_cov3[1:2]) # list_exp2 <- list_exp2[sort(names(list_exp2))] expect_equal(as.list(obj, stack = FALSE), list_exp2) length(obj) <- 3 - list_exp3 <- list(mu = c(list_exp2$mu, default_mu3[3]), cov = c(list_exp2$cov, default_cov3[3])) + list_exp3 <- list( + eta = c(list_exp2$eta, default_eta3[3]), + mu = c(list_exp2$mu, default_mu3[3]), cov = c(list_exp2$cov, default_cov3[3]) + ) # list_exp3 <- list_exp3[sort(names(list_exp3))] expect_equal(as.list(obj, stack = FALSE), list_exp3) @@ -239,6 +280,7 @@ test_that("basic modelValues class works", { obj_restored <- CmvClass$new(CppObj = obj) expect_equal(obj_restored[["mu"]][[1]], c(1, 2)) expect_equal(obj_restored[["mu"]][[2]], c(3, 4)) + expect_equal(obj_restored[["eta"]][[2]], 2.5) expect_equal(obj_restored$get_sizeList()$cov, c(3, 4)) rm(obj, mvh, obj_restored) @@ -249,13 +291,14 @@ test_that("modelValues hashedID works and is invariant to equivalent cases", { suppressWarnings(rm(list = "varInfo")) VI1 <- list( vars = list( + eta = list(name = "eta", nDim = 0), mu = list(name = "mu", nDim = 1), cov = list(name = "cov", nDim = 2) ) ) hash1 <- nimbleModel:::make_modelValues_hashID(VI1) VI2 <- VI1 - VI2$vars <- VI2$vars[c(2, 1)] + VI2$vars <- VI2$vars[c(3, 1, 2)] hash2 <- nimbleModel:::make_modelValues_hashID(VI2) expect_equal(hash1, hash2) VI3 <- VI2 @@ -290,6 +333,7 @@ test_that("modelValues hashedID works and is invariant to equivalent cases", { test_that("modelValues nClassBuilder types work in nCompiler", { varInfo <- list( vars = list( + eta = list(name = "eta", nDim = 0), mu = list(name = "mu", nDim = 1), cov = list(name = "cov", nDim = 2) ) @@ -334,6 +378,7 @@ test_that("modelValues nClassBuilder types work in nCompiler", { expect_equal(obj$mv$get_sizeList(), sizes_alt) obj$mv$resize(3) + expect_equal(obj$mv$eta |> as.list(), rep(list(0), 3)) expect_equal(obj$mv$cov |> as.list(), rep(list(matrix(0, nrow = 2, ncol = 1)), 3)) expect_equal(nCompiler::value(obj$mv, "cov") |> as.list(), rep(list(matrix(0, nrow = 2, ncol = 1)), 3)) expect_equal(obj$mv$getLength(), 3) @@ -347,10 +392,12 @@ test_that("modelValues nClassBuilder types work in nCompiler", { dup_mv_unc <- nimbleModel:::modelValues(varInfo) obj_unc <- dup_mv_unc$new() - sizes2 <- list(mu = 3, cov = c(1, 2)) + # Keep the default size for scalar eta. + sizes2 <- c(obj_unc$get_sizeList()["eta"], list(mu = 3, cov = c(1, 2))) obj_unc$set_sizeList(sizes2) obj_unc$resize(5) obj_unc$mu[[3]] <- 1:3 + obj_unc$eta[[3]] <- 2.5 obj$mv <- obj_unc # because we assigned an uncompiled to a compiled that already # had an instantiated object, it copied contents to the same @@ -363,6 +410,10 @@ test_that("modelValues nClassBuilder types work in nCompiler", { mu_exp[[3]] <- 1:3 expect_equal(obj_unc$mu |> as.list(), mu_exp) expect_equal(obj$mv$mu |> as.list(), mu_exp) + eta_exp <- rep(list(0), 5) + eta_exp[[3]] <- 2.5 + expect_equal(obj_unc$eta |> as.list(), eta_exp) + expect_equal(obj$mv$eta |> as.list(), eta_exp) expect_equal(obj_unc$getLength(), 5) expect_equal(obj$mv$getLength(), 5) @@ -421,31 +472,48 @@ test_that("as.matrix(modelValues) and matrix2MV work", { varInfo <- list( vars = list( eta = list(name = "eta", nDim = 0), + v1 = list(name = "v1", nDim = 1), mu = list(name = "mu", nDim = 1), cov = list(name = "cov", nDim = 2) - ) + ), + # No size for scalar eta, so it gets the default. + # v1 is a length-1 vector, which must be distinguished from scalar eta. + sizes = list(v1 = 1, mu = 2, cov = c(3, 4)) + ) + # Scalars are named without "[1]", as in nimble. + expected_colnames <- c( + "eta", "v1[1]", "mu[1]", "mu[2]", + nimbleModel:::dims_2_colnames(c(3, 4), var = "cov") ) mvClass <- nimbleModel:::make_modelValues_nClass(varInfo) obj <- mvClass$new() - sizes <- list(mu = 2, cov = c(3, 4)) - obj$set_sizeList(sizes) # Make an uncompiled object, # convert it to a matrix with as.matrix() # and invert that back to a new uncompiled object obj$resize(0) obj$resize(3) + obj$eta[[2]] <- 1.5 + obj$eta[[3]] <- 2.5 + obj$v1[[2]] <- 7 + obj$v1[[3]] <- 8 obj$mu[[2]] <- 5:6 obj$mu[[3]] <- 10:11 obj$cov[[2]] <- matrix(1:12, nrow = 3) obj$cov[[3]] <- obj$cov[[2]] + 100 mat <- obj |> as.matrix() + expect_identical(colnames(mat), expected_colnames) + flat <- as.list(obj, flatten = TRUE) + expect_identical(colnames(flat$eta), "eta") + expect_identical(colnames(flat$v1), "v1[1]") obj2 <- mvClass$new() junk <- nimbleModel:::matrix2mv(mat, obj2) expect_identical(junk, obj2) expect_equal(mat, obj2 |> as.matrix()) + expect_equal(obj$eta |> as.list(), obj2$eta |> as.list()) + expect_equal(obj$v1 |> as.list(), obj2$v1 |> as.list()) expect_equal(obj$mu |> as.list(), obj2$mu |> as.list()) # provide a way to get base class pointers @@ -463,26 +531,32 @@ test_that("as.matrix(modelValues) and matrix2MV work", { # Check that the compiled, specialized modelValues type works # as above for uncompiled. Cobj <- comp$mvClass$new() - Cobj$set_sizeList(sizes) Cobj$resize(0) Cobj$resize(3) + Cobj$eta[[2]] <- 1.5 + Cobj$eta[[3]] <- 2.5 + Cobj$v1[[2]] <- 7 + Cobj$v1[[3]] <- 8 Cobj$mu[[2]] <- 5:6 Cobj$mu[[3]] <- 10:11 Cobj$cov[[2]] <- matrix(1:12, nrow = 3) Cobj$cov[[3]] <- obj$cov[[2]] + 100 Cmat <- Cobj |> as.matrix() + expect_identical(colnames(Cmat), expected_colnames) expect_equal(mat, Cmat) # to compiled Cobj2 <- comp$mvClass$new() Cjunk <- nimbleModel:::matrix2mv(Cmat, Cobj2) expect_identical(Cjunk, Cobj2) expect_equal(Cmat, Cobj2 |> as.matrix()) + expect_equal(Cobj$eta |> as.list(), Cobj2$eta |> as.list()) expect_equal(Cobj$mu |> as.list(), Cobj2$mu |> as.list()) # to uncompiled length(obj2) <- 0 junk <- nimbleModel:::matrix2mv(Cmat, obj2) expect_identical(junk, obj2) expect_equal(Cmat, obj2 |> as.matrix()) + expect_equal(Cobj$eta |> as.list(), obj2$eta |> as.list()) expect_equal(Cobj$mu |> as.list(), obj2$mu |> as.list()) @@ -493,12 +567,17 @@ test_that("as.matrix(modelValues) and matrix2MV work", { expect_false(inherits(CbaseObj, class(Cobj)[1])) expect_equal(nCompiler::value(CbaseObj, "mu") |> as.list(), Cobj$mu |> as.list()) CbaseMat <- CbaseObj |> as.matrix() + expect_identical(colnames(CbaseMat), expected_colnames) expect_equal(CbaseMat, Cmat) + Cbase_flat <- as.list(CbaseObj, flatten = TRUE) + expect_identical(colnames(Cbase_flat$eta), "eta") + expect_identical(colnames(Cbase_flat$v1), "v1[1]") Cobj_temp <- comp$mvClass$new() CbaseObj2 <- comp$make_mvBase(Cobj_temp) CbaseJunk <- nimbleModel:::matrix2mv(CbaseMat, CbaseObj2) expect_identical(CbaseJunk, CbaseObj2) expect_equal(Cmat, CbaseObj2 |> as.matrix()) + expect_equal(nCompiler::value(CbaseObj, "eta") |> as.list(), nCompiler::value(CbaseObj2, "eta") |> as.list()) expect_equal(CbaseObj$mu |> as.list(), CbaseObj2$mu |> as.list()) rm(Cobj, Cobj2, Cjunk, CbaseObj, CbaseObj2, Cobj_temp) From e0ed9d2da875751de832727538ccdf096ebdbb99 Mon Sep 17 00:00:00 2001 From: perrydv Date: Mon, 26 Oct 2026 16:21:56 -0700 Subject: [PATCH 2/3] regenerate predefined classes. should not matter but something was not up to date with nCompiler. --- .../include/nimbleModel/predef/MVBase_nC/MVBase_nC_manifest.txt | 2 +- .../nimbleModel/predef/copier_nClass/copier_nClass_manifest.txt | 2 +- .../predef/declFunBase_nC/declFunBase_nClass_manifest.txt | 2 +- .../nimbleModel/predef/instr_nClass/instr_nClass_manifest.txt | 2 +- .../predef/mCopyMV_nC/multiCopierMV_nClass_manifest.txt | 2 +- .../include/nimbleModel/predef/mCopy_nC/mCopy_nC_manifest.txt | 2 +- .../predef/modelBase_nC/modelBase_nClass_manifest.txt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/nimbleModel/inst/include/nimbleModel/predef/MVBase_nC/MVBase_nC_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/MVBase_nC/MVBase_nC_manifest.txt index b8ae438..4092e71 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/MVBase_nC/MVBase_nC_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/MVBase_nC/MVBase_nC_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792987436.76702, class = c("POSIXct", +list(saved_at = structure(1793056666.55996, class = c("POSIXct", "POSIXt")), packet_name = "MVBase_nC", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "MVBase_nC_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/copier_nClass/copier_nClass_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/copier_nClass/copier_nClass_manifest.txt index 9c54968..ec2cdf0 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/copier_nClass/copier_nClass_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/copier_nClass/copier_nClass_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792987331.12855, class = c("POSIXct", +list(saved_at = structure(1793056472.33843, class = c("POSIXct", "POSIXt")), packet_name = "copier_nClass", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "copier_nClass_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/declFunBase_nC/declFunBase_nClass_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/declFunBase_nC/declFunBase_nClass_manifest.txt index 88949af..89e7014 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/declFunBase_nC/declFunBase_nClass_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/declFunBase_nC/declFunBase_nClass_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792987274.70172, class = c("POSIXct", +list(saved_at = structure(1793056375.6661, class = c("POSIXct", "POSIXt")), packet_name = "declFunBase_nClass", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "declFunBase_nClass_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/instr_nClass/instr_nClass_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/instr_nClass/instr_nClass_manifest.txt index 422935e..e0ea249 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/instr_nClass/instr_nClass_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/instr_nClass/instr_nClass_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792987228.03338, class = c("POSIXct", +list(saved_at = structure(1793056317.67685, class = c("POSIXct", "POSIXt")), packet_name = "instr_nClass", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "instr_nClass_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/mCopyMV_nC/multiCopierMV_nClass_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/mCopyMV_nC/multiCopierMV_nClass_manifest.txt index 79442d1..5d1c4c6 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/mCopyMV_nC/multiCopierMV_nClass_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/mCopyMV_nC/multiCopierMV_nClass_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792987409.09837, class = c("POSIXct", +list(saved_at = structure(1793056640.44678, class = c("POSIXct", "POSIXt")), packet_name = "multiCopierMV_nClass", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "multiCopierMV_nClass_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/mCopy_nC/mCopy_nC_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/mCopy_nC/mCopy_nC_manifest.txt index 71a3a57..d6a3595 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/mCopy_nC/mCopy_nC_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/mCopy_nC/mCopy_nC_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792987367.85232, class = c("POSIXct", +list(saved_at = structure(1793056548.82963, class = c("POSIXct", "POSIXt")), packet_name = "mCopy_nC", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "mCopy_nC_preamble.cpp", diff --git a/nimbleModel/inst/include/nimbleModel/predef/modelBase_nC/modelBase_nClass_manifest.txt b/nimbleModel/inst/include/nimbleModel/predef/modelBase_nC/modelBase_nClass_manifest.txt index 433df2a..cc6d6fb 100644 --- a/nimbleModel/inst/include/nimbleModel/predef/modelBase_nC/modelBase_nClass_manifest.txt +++ b/nimbleModel/inst/include/nimbleModel/predef/modelBase_nC/modelBase_nClass_manifest.txt @@ -1,4 +1,4 @@ -list(saved_at = structure(1792987296.24025, class = c("POSIXct", +list(saved_at = structure(1793056441.24624, class = c("POSIXct", "POSIXt")), packet_name = "modelBase_nClass", elements = c("preamble", "cppContent", "hContent", "filebase", "post_cpp_compiler", "copyFiles", "depends"), files = list(preamble = "modelBase_nClass_preamble.cpp", From 9818c2df4032cc2a97c275b35382b32885b75c0f Mon Sep 17 00:00:00 2001 From: perrydv Date: Tue, 27 Oct 2026 14:29:22 -0700 Subject: [PATCH 3/3] styler pass --- nimbleModel/R/indexRuleBlock.R | 10 +- nimbleModel/inst/generate_predefined.R | 14 +-- nimbleModel/tests/testthat/test-nodeIDs.R | 136 +++++++++++++--------- 3 files changed, 96 insertions(+), 64 deletions(-) diff --git a/nimbleModel/R/indexRuleBlock.R b/nimbleModel/R/indexRuleBlock.R index c4bd34f..fa3c064 100644 --- a/nimbleModel/R/indexRuleBlock.R +++ b/nimbleModel/R/indexRuleBlock.R @@ -46,11 +46,11 @@ indexRuleBlockClass <- R6Class( getIDs = function(indexRange) { init <- as.integer(setupResults$fromMin + setupResults$offset) switch(class(indexRange)[1], - indexRangeScalarClass = as.integer(indexRange$value) - init + 1L, - indexRangeSequenceClass = (indexRange$start - init + 1):(indexRange$end - init + 1), - indexRangeMatrixClass = as.integer(c(indexRange$values)) - init + 1L, - stop("invalid type of indexRange provided for creating IDs") - ) + indexRangeScalarClass = as.integer(indexRange$value) - init + 1L, + indexRangeSequenceClass = (indexRange$start - init + 1):(indexRange$end - init + 1), + indexRangeMatrixClass = as.integer(c(indexRange$values)) - init + 1L, + stop("invalid type of indexRange provided for creating IDs") + ) }, invertIDs = function(relativeNodeIDs) { if (setupResults$fromMin + setupResults$offset != 1) { diff --git a/nimbleModel/inst/generate_predefined.R b/nimbleModel/inst/generate_predefined.R index cfd161d..f321d0b 100644 --- a/nimbleModel/inst/generate_predefined.R +++ b/nimbleModel/inst/generate_predefined.R @@ -1,43 +1,43 @@ ## # To update the set of predefined nClasses: ## ## # generate new predef/instr_nC. Move that directly to package code inst/nimbleModel/predef/instr_nC (i.e. move to package) -nCompiler::nCompile(instr_nClass = nimbleModel:::instr_nClass, control=list(generate_predefined=TRUE)) +nCompiler::nCompile(instr_nClass = nimbleModel:::instr_nClass, control = list(generate_predefined = TRUE)) test <- nCompiler::nCompile(instr_nClass = nimbleModel:::instr_nClass) ## # ## # generate new predef/declFunBase_nC. Move to package. ## # You should see "#include " in the hContent ## # after declaration of declFunBase_nClass ## # and "// [[Rcpp::depends(nimbleModel)]]" in the cppContent -nCompiler::nCompile(nimbleModel:::declFunBase_nClass, control=list(generate_predefined=TRUE)) +nCompiler::nCompile(nimbleModel:::declFunBase_nClass, control = list(generate_predefined = TRUE)) test <- nCompiler::nCompile(nimbleModel:::declFunBase_nClass) ## # ## # generate new predef/modelBase_nC. Move to package. ## # You should see "#include " in the hContent ## # after the declaration of modelBase_nClass. ## # and "// [[Rcpp::depends(nimbleModel)]]" in the cppContent -nCompiler::nCompile(modelBase_nClass = nimbleModel:::modelBase_nClass, control=list(generate_predefined=TRUE)) +nCompiler::nCompile(modelBase_nClass = nimbleModel:::modelBase_nClass, control = list(generate_predefined = TRUE)) test <- nCompiler::nCompile(nimbleModel:::modelBase_nClass) ## # generate new predef/copier_nClass. Move to package. ## # You should see "#include " in the hContent BEFORE the class declaration ## # and "// [[Rcpp::depends(nimbleModel)]]" in the cppContent -nCompiler::nCompile(copier_nClass = nimbleModel:::copier_nClass, control=list(generate_predefined=TRUE)) +nCompiler::nCompile(copier_nClass = nimbleModel:::copier_nClass, control = list(generate_predefined = TRUE)) test <- nCompiler::nCompile(nimbleModel:::copier_nClass) ## # generate new predef/mCopy_nC Move to package. ## # You should see "#include " in the hContent BEFORE the class declaration ## # and "// [[Rcpp::depends(nimbleModel)]]" in the cppContent -nCompiler::nCompile(multiCopier_nClass = nimbleModel:::multiCopier_nClass, control=list(generate_predefined=TRUE)) +nCompiler::nCompile(multiCopier_nClass = nimbleModel:::multiCopier_nClass, control = list(generate_predefined = TRUE)) test <- nCompiler::nCompile(nimbleModel:::multiCopier_nClass) ## # generate new predef/mCopyMV_nC. Move to package. ## # You should see "#include " in the hContent BEFORE the class declaration ## # and "// [[Rcpp::depends(nimbleModel)]]" in the cppContent -nCompiler::nCompile(multiCopierMV_nClass = nimbleModel:::multiCopierMV_nClass, control=list(generate_predefined=TRUE)) +nCompiler::nCompile(multiCopierMV_nClass = nimbleModel:::multiCopierMV_nClass, control = list(generate_predefined = TRUE)) test <- nCompiler::nCompile(nimbleModel:::multiCopierMV_nClass) ## # generate new predef/MVBase_nC Move to package. ## # You should see "#include " in the hContent ## # and "// [[Rcpp::depends(nimbleModel)]]" in the cppContent -nCompiler::nCompile(modelValuesBase_nClass = nimbleModel:::modelValuesBase_nClass, control=list(generate_predefined=TRUE)) +nCompiler::nCompile(modelValuesBase_nClass = nimbleModel:::modelValuesBase_nClass, control = list(generate_predefined = TRUE)) test <- nCompiler::nCompile(nimbleModel:::modelValuesBase_nClass) diff --git a/nimbleModel/tests/testthat/test-nodeIDs.R b/nimbleModel/tests/testthat/test-nodeIDs.R index 1a6d985..3909aa5 100644 --- a/nimbleModel/tests/testthat/test-nodeIDs.R +++ b/nimbleModel/tests/testthat/test-nodeIDs.R @@ -83,46 +83,62 @@ test_that("basic tests of mapping indexing to nodes via loopIndexingRule$invert" test_that("basic tests of nodeIDs", { code <- nimbleCode({ - for(i in 1:10) - y[i] ~ dnorm(0,1) + for (i in 1:10) { + y[i] ~ dnorm(0, 1) + } }) - + m <- nimbleModel(code) decl <- m$modelDef$declRules$y$rules[[1]] - - expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new('.loop[5]')), 5L) - expect_identical(decl$getLoopIndexingFromIDs(5)$toChar(), - 'index 1: 5') - expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new('.loop[1:5]')), 1:5) - expect_identical(decl$getLoopIndexingFromIDs(1:5)$toChar(), - 'index 1: 1:5') - expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new('.loop[3:5]')), 3:5) - expect_identical(decl$getLoopIndexingFromIDs(3:5)$toChar(), - 'index 1: 3:5') - - expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new('.loop[9:14]')), 9:14) - expect_identical(decl$getLoopIndexingFromIDs(9:14)$toChar(), - 'index 1: 9:14') - - expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new('.loop[c(2, 4)]')), c(2L,4L)) - expect_identical(decl$getLoopIndexingFromIDs(c(2,4))$toChar(), - 'index 1: c(2, 4)') + + expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new(".loop[5]")), 5L) + expect_identical( + decl$getLoopIndexingFromIDs(5)$toChar(), + "index 1: 5" + ) + expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new(".loop[1:5]")), 1:5) + expect_identical( + decl$getLoopIndexingFromIDs(1:5)$toChar(), + "index 1: 1:5" + ) + expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new(".loop[3:5]")), 3:5) + expect_identical( + decl$getLoopIndexingFromIDs(3:5)$toChar(), + "index 1: 3:5" + ) + + expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new(".loop[9:14]")), 9:14) + expect_identical( + decl$getLoopIndexingFromIDs(9:14)$toChar(), + "index 1: 9:14" + ) + + expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new(".loop[c(2, 4)]")), c(2L, 4L)) + expect_identical( + decl$getLoopIndexingFromIDs(c(2, 4))$toChar(), + "index 1: c(2, 4)" + ) code <- nimbleCode({ - for(i in c(2,4,7,9)) - y[i] ~ dnorm(0,1) + for (i in c(2, 4, 7, 9)) { + y[i] ~ dnorm(0, 1) + } }) - + m <- nimbleModel(code) decl <- m$modelDef$declRules$y$rules[[1]] - - expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new('.loop[1:5]')), 1:2) - expect_identical(decl$getLoopIndexingFromIDs(1:2)$toChar(), - 'index 1: c(2, 4)') - expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new('.loop[c(4, 9)]')), c(2L,4L)) - expect_identical(decl$getLoopIndexingFromIDs(c(2,4))$toChar(), - 'index 1: c(4, 9)') + expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new(".loop[1:5]")), 1:2) + expect_identical( + decl$getLoopIndexingFromIDs(1:2)$toChar(), + "index 1: c(2, 4)" + ) + + expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new(".loop[c(4, 9)]")), c(2L, 4L)) + expect_identical( + decl$getLoopIndexingFromIDs(c(2, 4))$toChar(), + "index 1: c(4, 9)" + ) code <- nimbleCode({ for (i in 3:10) { @@ -166,29 +182,45 @@ test_that("nodeIDs with multiple loops", { m <- nimbleModel(code) decl <- m$modelDef$declRules$y$rules[[1]] - expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new('.loop[2,4,3]')), - 38L) - expect_identical(decl$getLoopIndexingFromIDs(38)$toChar(), - 'index 1: 2, index 2: 4, index 3: 3') + expect_identical( + decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new(".loop[2,4,3]")), + 38L + ) + expect_identical( + decl$getLoopIndexingFromIDs(38)$toChar(), + "index 1: 2, index 2: 4, index 3: 3" + ) - ids <- as.integer(c(28:30,33:35,38:40,48:50,53:55,58:60)) - expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new('.loop[2:3,2:4,3:5]')), - ids) - expect_identical(decl$getLoopIndexingFromIDs(ids)$toChar(), - 'index 1: 2:3, index 2: 2:4, index 3: 3:5') + ids <- as.integer(c(28:30, 33:35, 38:40, 48:50, 53:55, 58:60)) + expect_identical( + decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new(".loop[2:3,2:4,3:5]")), + ids + ) + expect_identical( + decl$getLoopIndexingFromIDs(ids)$toChar(), + "index 1: 2:3, index 2: 2:4, index 3: 3:5" + ) # do with arbitrary subsetting, separable - ids <- as.integer(c(8,10,13,15,18,20,48,50,53,55,58,60)) - expect_identical(decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new('.loop[c(1,3),2:4,c(3,5)]')), - ids) - expect_identical(decl$getLoopIndexingFromIDs(ids)$toChar(), - 'index 1: c(1, 3), index 2: 2:4, index 3: c(3, 5)') - + ids <- as.integer(c(8, 10, 13, 15, 18, 20, 48, 50, 53, 55, 58, 60)) + expect_identical( + decl$getIDsFromLoopIndexing(loopIndexingRangeClass$new(".loop[c(1,3),2:4,c(3,5)]")), + ids + ) + expect_identical( + decl$getLoopIndexingFromIDs(ids)$toChar(), + "index 1: c(1, 3), index 2: 2:4, index 3: c(3, 5)" + ) + # do with arbitrary subsetting, nonseparable - ids <- as.integer(c(46,51,56, 30,35,40)) - indexingRange <- loopIndexingRangeClass$new(list(newIndexRange(quote(2:4)), - newIndexRange(matrix(c(5,2,1,3),ncol=2,byrow=TRUE))), - rangeToIndexSlot=list(2,c(3,1))) + ids <- as.integer(c(46, 51, 56, 30, 35, 40)) + indexingRange <- loopIndexingRangeClass$new( + list( + newIndexRange(quote(2:4)), + newIndexRange(matrix(c(5, 2, 1, 3), ncol = 2, byrow = TRUE)) + ), + rangeToIndexSlot = list(2, c(3, 1)) + ) expect_identical(decl$getIDsFromLoopIndexing(indexingRange), ids) expect_identical( decl$getLoopIndexingFromIDs(ids)$extractIndexRange(1:3)$getValuesAsMatrix(), @@ -210,7 +242,7 @@ test_that("nodeIDs with multiple loops", { decl <- m$modelDef$declRules$y$rules[[1]] ids <- as.integer(c(28:30, 33:35, 38:40, 48:50, 53:55, 58:60)) - indexingRange <- decl$loopIndexingRule$apply('y[4:5,3:5,6:8]') + indexingRange <- decl$loopIndexingRule$apply("y[4:5,3:5,6:8]") expect_identical(decl$getIDsFromLoopIndexing(indexingRange), ids) expect_identical( decl$getLoopIndexingFromIDs(ids)$toChar(), @@ -219,7 +251,7 @@ test_that("nodeIDs with multiple loops", { # do with arbitrary subsetting, separable - indexingRange <- decl$loopIndexingRule$apply('y[c(3,5),3:5,c(6,8)]') + indexingRange <- decl$loopIndexingRule$apply("y[c(3,5),3:5,c(6,8)]") ids <- as.integer(c(8, 10, 13, 15, 18, 20, 48, 50, 53, 55, 58, 60)) expect_identical(decl$getIDsFromLoopIndexing(indexingRange), ids) expect_identical(