From 7331b3acb339ea3845864f083dd25fe568628b68 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 6 May 2026 05:30:54 +0000 Subject: [PATCH 1/3] Initial plan From d329174078a0d5440deedc7dd88a6f5f9e20df29 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 6 May 2026 05:40:55 +0000 Subject: [PATCH 2/3] fix: avoid memory overflow in ensure_no_na for large sparse matrices with mode=lower/upper Agent-Logs-Url: https://github.com/igraph/rigraph/sessions/a080274e-c869-44c6-b491-4748a81bfc9c Co-authored-by: schochastics <17147355+schochastics@users.noreply.github.com> --- R/adjacency.R | 5 +++-- R/utils-assert-args.R | 12 ++++++++++-- tests/testthat/test-adjacency.R | 34 +++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/R/adjacency.R b/R/adjacency.R index 65b4eb21411..10497e4f3ff 100644 --- a/R/adjacency.R +++ b/R/adjacency.R @@ -494,8 +494,9 @@ graph.adjacency.sparse <- function( } vc <- nrow(adjmatrix) - # Exit early for empty graphs - if (vc == 1 || Matrix::nnzero(adjmatrix) == 0) { + # Exit early for empty graphs. Use na.counted = TRUE so that NA entries + # (which are stored explicitly) do not cause nnzero() to return NA. + if (vc == 1 || Matrix::nnzero(adjmatrix, na.counted = TRUE) == 0) { return(make_empty_graph(n = vc, directed = (mode == "directed"))) } diff --git a/R/utils-assert-args.R b/R/utils-assert-args.R index cfb2ddf3025..c80e7cb9cfd 100644 --- a/R/utils-assert-args.R +++ b/R/utils-assert-args.R @@ -66,9 +66,17 @@ igraph_match_arg <- function( #' @importFrom rlang caller_env ensure_no_na <- function(x, what, mode = "", call = caller_env()) { if (mode == "upper") { - x <- x[upper.tri(x)] + if (inherits(x, "sparseMatrix")) { + x <- Matrix::triu(x)@x + } else { + x <- x[upper.tri(x)] + } } else if (mode == "lower") { - x <- x[lower.tri(x)] + if (inherits(x, "sparseMatrix")) { + x <- Matrix::tril(x)@x + } else { + x <- x[lower.tri(x)] + } } if (anyNA(x)) { cli::cli_abort( diff --git a/tests/testthat/test-adjacency.R b/tests/testthat/test-adjacency.R index c4f2669202b..67755897b20 100644 --- a/tests/testthat/test-adjacency.R +++ b/tests/testthat/test-adjacency.R @@ -879,3 +879,37 @@ test_that("graph_from_adjacency Na check for upper/lower", { ) ) }) + +test_that("graph_from_adjacency Na check for upper/lower with sparse matrices", { + # Sparse matrix with NA only in upper triangle: mode="upper" should error, + # mode="lower" should succeed + sp <- Matrix::sparseMatrix( + i = c(1, 2, 1), + j = c(2, 1, 1), + x = c(NA_real_, 1, 1), + dims = c(3, 3) + ) + expect_error( + graph_from_adjacency_matrix(sp, mode = "upper", weighted = TRUE), + "contains NAs" + ) + expect_no_error( + graph_from_adjacency_matrix(sp, mode = "lower", weighted = TRUE) + ) + + # Sparse matrix with NA only in lower triangle: mode="lower" should error, + # mode="upper" should succeed + sp2 <- Matrix::sparseMatrix( + i = c(2, 1, 1), + j = c(1, 2, 1), + x = c(NA_real_, 1, 1), + dims = c(3, 3) + ) + expect_error( + graph_from_adjacency_matrix(sp2, mode = "lower", weighted = TRUE), + "contains NAs" + ) + expect_no_error( + graph_from_adjacency_matrix(sp2, mode = "upper", weighted = TRUE) + ) +}) From 0f89ecf352ab7fe0128814ae6e73154da25f7242 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 6 May 2026 05:41:22 +0000 Subject: [PATCH 3/3] style: fix test name capitalization (Na -> NA) Agent-Logs-Url: https://github.com/igraph/rigraph/sessions/a080274e-c869-44c6-b491-4748a81bfc9c Co-authored-by: schochastics <17147355+schochastics@users.noreply.github.com> --- tests/testthat/test-adjacency.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-adjacency.R b/tests/testthat/test-adjacency.R index 67755897b20..b43e54c3450 100644 --- a/tests/testthat/test-adjacency.R +++ b/tests/testthat/test-adjacency.R @@ -880,7 +880,7 @@ test_that("graph_from_adjacency Na check for upper/lower", { ) }) -test_that("graph_from_adjacency Na check for upper/lower with sparse matrices", { +test_that("graph_from_adjacency NA check for upper/lower with sparse matrices", { # Sparse matrix with NA only in upper triangle: mode="upper" should error, # mode="lower" should succeed sp <- Matrix::sparseMatrix(