Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions R/aFIPC.R
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ autoFIPC <-

if (!is.character(itemtype)) stop('Security Error: itemtype must be a character vector')
nItems <- NA_integer_
if (is.data.frame(newformXData) || is.matrix(newformXData)) nItems <- ncol(as.data.frame(newformXData))
else if (is.data.frame(oldformYData) || is.matrix(oldformYData)) nItems <- ncol(as.data.frame(oldformYData))
# Optimization: Use ncol() directly instead of coercing to data.frame to avoid O(N) memory allocation and copy overhead
if (is.data.frame(newformXData) || is.matrix(newformXData)) nItems <- ncol(newformXData)
# Optimization: Use ncol() directly instead of coercing to data.frame to avoid O(N) memory allocation and copy overhead
else if (is.data.frame(oldformYData) || is.matrix(oldformYData)) nItems <- ncol(oldformYData)
if (!is.na(nItems) && !(length(itemtype) == 1 || length(itemtype) == nItems)) stop(sprintf('Security Error: itemtype must be length 1 or length %d (number of items).', nItems))

# boolean parameter validation
Expand Down
35 changes: 35 additions & 0 deletions tests/testthat/test-ncol_optimization.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
test_that("ncol() optimization correctly determines number of items from matrix", {
# Test the newformXData path explicitly.
expect_error(
aFIPC::autoFIPC(
newformXData = matrix(c(1, 2), nrow = 1, dimnames = list(NULL, c("A", "B"))),
oldformYData = data.frame(A=2, B=3),
newformCommonItemNames = c('A'),
oldformCommonItemNames = c('A'),
itemtype = c("2PL", "2PL", "2PL")
),
"Security Error: itemtype must be length 1 or length 2 \\(number of items\\)."
)

# Test the oldformYData path explicitly.
# We construct an S4 SingleGroupClass from mirt using mock data but provide sufficient
# parameters to prevent mirt from crashing during internal check inside `aFIPC`.

dummy_data <- matrix(sample(c(0, 1), 100, replace=TRUE), 20, 5)
colnames(dummy_data) <- paste0("Item", 1:5)

suppressMessages(suppressWarnings({
real_mirt_model <- mirt::mirt(dummy_data, 1, itemtype = "2PL", TOL = 0.5, verbose=FALSE)
}))

expect_error(
aFIPC::autoFIPC(
newformXData = real_mirt_model,
oldformYData = matrix(c(1, 2, 3), nrow = 1, dimnames = list(NULL, c("A", "B", "C"))),
newformCommonItemNames = c('A'),
oldformCommonItemNames = c('A'),
itemtype = c("2PL", "2PL")
),
"Security Error: itemtype must be length 1 or length 3 \\(number of items\\)."
)
})
Loading