diff --git a/R/aaa-auto.R b/R/aaa-auto.R index f394c14d47..26adfa5868 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -26,13 +26,14 @@ add_edges_impl <- function( ) { # Argument checks ensure_igraph(graph) + edges <- as_igraph_vs(graph, edges) on.exit(.Call(R_igraph_finalizer)) # Function call res <- .Call( R_igraph_add_edges, graph, - edges + edges - 1 ) res @@ -354,6 +355,7 @@ get_eids_impl <- function( ) { # Argument checks ensure_igraph(graph) + pairs <- as_igraph_vs(graph, pairs) directed <- as.logical(directed) error <- as.logical(error) @@ -362,7 +364,7 @@ get_eids_impl <- function( res <- .Call( R_igraph_get_eids, graph, - pairs, + pairs - 1, directed, error ) @@ -7244,7 +7246,7 @@ edgelist_percolation_impl <- function( # Function call res <- .Call( R_igraph_edgelist_percolation, - edges + edges - 1 ) res @@ -8763,6 +8765,7 @@ similarity_dice_pairs_impl <- function( ) { # Argument checks ensure_igraph(graph) + pairs <- as_igraph_vs(graph, pairs) mode <- switch_igraph_arg( mode, "out" = 1L, @@ -8777,7 +8780,7 @@ similarity_dice_pairs_impl <- function( res <- .Call( R_igraph_similarity_dice_pairs, graph, - pairs, + pairs - 1, mode, loops ) @@ -8883,6 +8886,7 @@ similarity_jaccard_pairs_impl <- function( ) { # Argument checks ensure_igraph(graph) + pairs <- as_igraph_vs(graph, pairs) mode <- switch_igraph_arg( mode, "out" = 1L, @@ -8897,7 +8901,7 @@ similarity_jaccard_pairs_impl <- function( res <- .Call( R_igraph_similarity_jaccard_pairs, graph, - pairs, + pairs - 1, mode, loops ) diff --git a/R/components.R b/R/components.R index ffe1459634..5b344c3905 100644 --- a/R/components.R +++ b/R/components.R @@ -204,18 +204,15 @@ decompose <- function( ) { ensure_igraph(graph) mode <- igraph_match_arg(mode) - mode <- switch(mode, "weak" = 1L, "strong" = 2L) if (is.na(max.comps)) { max.comps <- -1 } - on.exit(.Call(Rx_igraph_finalizer)) - .Call( - Rx_igraph_decompose, + decompose_impl( graph, - as.numeric(mode), - as.numeric(max.comps), - as.numeric(min.vertices) + mode, + max.comps, + min.vertices ) } diff --git a/R/conversion.R b/R/conversion.R index 92d10cab6a..0d73ec08d5 100644 --- a/R/conversion.R +++ b/R/conversion.R @@ -223,7 +223,6 @@ get.adjacency.dense <- function( graph, type = c("both", "upper", "lower"), attr = NULL, - weights = NULL, loops = c("once", "twice", "ignore"), names = TRUE ) { @@ -243,20 +242,17 @@ get.adjacency.dense <- function( ) } loops <- igraph_match_arg(loops) - loops <- switch(loops, "ignore" = 0L, "twice" = 1L, "once" = 2L) - - if (!is.null(weights)) { - weights <- as.numeric(weights) + # Map "ignore" to "none" for get_adjacency_impl + if (loops == "ignore") { + loops <- "none" } if (is.null(attr)) { - on.exit(.Call(Rx_igraph_finalizer)) - type <- switch(type, "upper" = 0, "lower" = 1, "both" = 2) - res <- .Call( - Rx_igraph_get_adjacency, + # FIXME: Use get_adjacency_impl() also for non-NULL attr + res <- get_adjacency_impl( graph, - as.numeric(type), - weights, + type, + weights = numeric(), loops ) } else { @@ -287,67 +283,33 @@ get.adjacency.sparse <- function( type <- igraph_match_arg(type) - vc <- vcount(graph) - - el <- as_edgelist(graph, names = FALSE) - use.last.ij <- FALSE - - if (!is.null(attr)) { + # Prepare weights parameter + if (is.null(attr)) { + weights <- numeric() + } else { attr <- as.character(attr) if (!attr %in% edge_attr_names(graph)) { cli::cli_abort("No such edge attribute", call = call) } - value <- edge_attr(graph, name = attr) - if (!is.numeric(value) && !is.logical(value)) { + weights <- edge_attr(graph, name = attr) + if (!is.numeric(weights) && !is.logical(weights)) { cli::cli_abort( "Matrices must be either numeric or logical, and the edge attribute is not", call = call ) } - } else { - value <- rep(1, nrow(el)) } - if (is_directed(graph)) { - res <- Matrix::sparseMatrix( - dims = c(vc, vc), - i = el[, 1], - j = el[, 2], - x = value, - use.last.ij = use.last.ij - ) - } else { - if (type == "upper") { - ## upper - res <- Matrix::sparseMatrix( - dims = c(vc, vc), - i = pmin(el[, 1], el[, 2]), - j = pmax(el[, 1], el[, 2]), - x = value, - use.last.ij = use.last.ij - ) - } else if (type == "lower") { - ## lower - res <- Matrix::sparseMatrix( - dims = c(vc, vc), - i = pmax(el[, 1], el[, 2]), - j = pmin(el[, 1], el[, 2]), - x = value, - use.last.ij = use.last.ij - ) - } else if (type == "both") { - ## both - res <- Matrix::sparseMatrix( - dims = c(vc, vc), - i = pmin(el[, 1], el[, 2]), - j = pmax(el[, 1], el[, 2]), - x = value, - symmetric = TRUE, - use.last.ij = use.last.ij - ) - res <- as(res, "generalMatrix") - } - } + # Use the library implementation + tmp <- get_adjacency_sparse_impl( + graph, + type, + weights, + loops = "once" + ) + + # Convert to proper Matrix object + res <- igraph.i.spMatrix(tmp) if (names && "name" %in% vertex_attr_names(graph)) { colnames(res) <- rownames(res) <- V(graph)$name @@ -427,7 +389,6 @@ as_adjacency_matrix <- function( graph, type = type, attr = attr, - weights = NULL, names = names, loops = "once" ) diff --git a/R/flow.R b/R/flow.R index e569a0e13a..4dd3f697cc 100644 --- a/R/flow.R +++ b/R/flow.R @@ -417,12 +417,11 @@ min_cut <- function( } } else { if (value.only) { - res <- .Call( - Rx_igraph_st_mincut_value, - graph, - as_igraph_vs(graph, source) - 1, - as_igraph_vs(graph, target) - 1, - capacity + res <- st_mincut_value_impl( + graph = graph, + source = source, + target = target, + capacity = capacity ) } else { res <- st_mincut_impl( @@ -526,12 +525,10 @@ vertex_connectivity <- function( if (is.null(source) && is.null(target)) { vertex_connectivity_impl(graph = graph, checks = checks) } else if (!is.null(source) && !is.null(target)) { - on.exit(.Call(Rx_igraph_finalizer)) - .Call( - Rx_igraph_st_vertex_connectivity, - graph, - as_igraph_vs(graph, source) - 1, - as_igraph_vs(graph, target) - 1 + st_vertex_connectivity_impl( + graph = graph, + source = source, + target = target ) } else { cli::cli_abort(c( @@ -631,12 +628,10 @@ edge_connectivity <- function( if (is.null(source) && is.null(target)) { edge_connectivity_impl(graph = graph, checks = checks) } else if (!is.null(source) && !is.null(target)) { - on.exit(.Call(Rx_igraph_finalizer)) - .Call( - Rx_igraph_st_edge_connectivity, - graph, - as_igraph_vs(graph, source) - 1, - as_igraph_vs(graph, target) - 1 + st_edge_connectivity_impl( + graph = graph, + source = source, + target = target ) } else { cli::cli_abort(c( @@ -653,12 +648,10 @@ edge_disjoint_paths <- function(graph, source = NULL, target = NULL) { if (is.null(source) || is.null(target)) { cli::cli_abort("Both source and target must be given") } - on.exit(.Call(Rx_igraph_finalizer)) - .Call( - Rx_igraph_edge_disjoint_paths, - graph, - as_igraph_vs(graph, source) - 1, - as_igraph_vs(graph, target) - 1 + edge_disjoint_paths_impl( + graph = graph, + source = source, + target = target ) } @@ -670,12 +663,10 @@ vertex_disjoint_paths <- function(graph, source = NULL, target = NULL) { cli::cli_abort("Both source and target must be given") } - on.exit(.Call(Rx_igraph_finalizer)) - .Call( - Rx_igraph_vertex_disjoint_paths, - graph, - as_igraph_vs(graph, source) - 1, - as_igraph_vs(graph, target) - 1 + vertex_disjoint_paths_impl( + graph = graph, + source = source, + target = target ) } diff --git a/R/games.R b/R/games.R index 5e95805757..dd72d790b0 100644 --- a/R/games.R +++ b/R/games.R @@ -826,8 +826,9 @@ aging.prefatt.game <- function( #' @param n Number of vertices. #' @param power The power of the preferential attachment, the default is one, #' i.e. linear preferential attachment. -#' @param m Numeric constant, the number of edges to add in each time step This -#' argument is only used if both `out.dist` and `out.seq` are omitted +#' @param m Numeric constant, the number of edges to add in each time step, +#' defaults to 1. +#' This argument is only used if both `out.dist` and `out.seq` are omitted #' or NULL. #' @param out.dist Numeric vector, the distribution of the number of edges to #' add in each time step. This argument is only used if the `out.seq` @@ -911,15 +912,13 @@ sample_pa <- function( cli::cli_warn("{.arg m} is zero, graph will be empty.") } - if (is.null(m) && is.null(out.dist) && is.null(out.seq)) { + if (is.null(m)) { m <- 1 } + m <- as.numeric(m) n <- as.numeric(n) power <- as.numeric(power) - if (!is.null(m)) { - m <- as.numeric(m) - } if (!is.null(out.dist)) { out.dist <- as.numeric(out.dist) } @@ -943,25 +942,23 @@ sample_pa <- function( } algorithm <- igraph_match_arg(algorithm) - algorithm1 <- switch( + algorithm_impl <- switch( algorithm, - "psumtree" = 1, - "psumtree-multiple" = 2, - "bag" = 0 + "psumtree" = "psumtree", + "psumtree-multiple" = "psumtree_multiple", + "bag" = "bag" ) - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_barabasi_game, - n, - power, - m, - out.seq, - out.pref, - zero.appeal, - directed, - algorithm1, - start.graph + res <- barabasi_game_impl( + n = n, + power = power, + m = m, + outseq = out.seq, + outpref = out.pref, + A = zero.appeal, + directed = directed, + algo = algorithm_impl, + start_from = start.graph ) if (igraph_opt("add.params")) { @@ -1415,24 +1412,22 @@ sample_degseq <- function( } # numbers from https://github.com/igraph/igraph/blob/640083c88bf85fd322ff7b748b9b4e16ebe32aa2/include/igraph_constants.h#L94 - method1 <- switch( + method_impl <- switch( method, - "configuration" = 0, - "vl" = 1, - "fast.heur.simple" = 2, - "configuration.simple" = 3, - "edge.switching.simple" = 4 + "configuration" = "configuration", + "vl" = "vl", + "fast.heur.simple" = "fast_heur_simple", + "configuration.simple" = "configuration_simple", + "edge.switching.simple" = "edge_switching_simple" ) if (!is.null(in.deg)) { in.deg <- as.numeric(in.deg) } - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_degree_sequence_game, - as.numeric(out.deg), - in.deg, - as.numeric(method1) + res <- degree_sequence_game_impl( + out_deg = out.deg, + in_deg = in.deg, + method = method_impl ) if (igraph_opt("add.params")) { res$name <- "Degree sequence random graph" @@ -1683,36 +1678,33 @@ sample_pa_age <- function( out.seq <- numeric() } - on.exit(.Call(Rx_igraph_finalizer)) res <- if (is.null(time.window)) { - .Call( - Rx_igraph_barabasi_aging_game, - as.numeric(n), - as.numeric(pa.exp), - as.numeric(aging.exp), - as.numeric(aging.bin), - m, - out.seq, - out.pref, - as.numeric(zero.deg.appeal), - as.numeric(zero.age.appeal), - as.numeric(deg.coef), - as.numeric(age.coef), - directed + barabasi_aging_game_impl( + nodes = n, + m = m, + outseq = out.seq, + outpref = out.pref, + pa_exp = pa.exp, + aging_exp = aging.exp, + aging_bin = aging.bin, + zero_deg_appeal = zero.deg.appeal, + zero_age_appeal = zero.age.appeal, + deg_coef = deg.coef, + age_coef = age.coef, + directed = directed ) } else { - .Call( - Rx_igraph_recent_degree_aging_game, - as.numeric(n), - as.numeric(pa.exp), - as.numeric(aging.exp), - as.numeric(aging.bin), - m, - out.seq, - out.pref, - as.numeric(zero.deg.appeal), - directed, - time.window + recent_degree_aging_game_impl( + nodes = n, + m = m, + outseq = out.seq, + outpref = out.pref, + pa_exp = pa.exp, + aging_exp = aging.exp, + aging_bin = aging.bin, + window = time.window, + zero_appeal = zero.deg.appeal, + directed = directed ) } if (igraph_opt("add.params")) { @@ -1816,19 +1808,17 @@ sample_traits_callaway <- function( pref.matrix = matrix(1, types, types), directed = FALSE ) { - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_callaway_traits_game, - as.double(nodes), - as.double(types), - as.double(edge.per.step), - as.double(type.dist), - matrix( + res <- callaway_traits_game_impl( + nodes = nodes, + types = types, + edges_per_step = edge.per.step, + type_dist = type.dist, + pref_matrix = matrix( as.double(pref.matrix), types, types ), - as.logical(directed) + directed = directed ) if (igraph_opt("add.params")) { res$name <- "Trait-based Callaway graph" @@ -1871,15 +1861,13 @@ sample_traits <- function( pref.matrix = matrix(1, types, types), directed = FALSE ) { - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_establishment_game, - as.double(nodes), - as.double(types), - as.double(k), - as.double(type.dist), - matrix(as.double(pref.matrix), types, types), - as.logical(directed) + res <- establishment_game_impl( + nodes = nodes, + types = types, + k = k, + type_dist = type.dist, + pref_matrix = matrix(as.double(pref.matrix), types, types), + directed = directed ) if (igraph_opt("add.params")) { res$name <- "Trait-based growing graph" @@ -2166,14 +2154,11 @@ asym_pref <- function( connect <- function(graph, order, mode = c("all", "out", "in", "total")) { ensure_igraph(graph) mode <- igraph_match_arg(mode) - mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3, "total" = 3) - on.exit(.Call(Rx_igraph_finalizer)) - .Call( - Rx_igraph_connect_neighborhood, - graph, - as.numeric(order), - as.numeric(mode) + connect_neighborhood_impl( + graph = graph, + order = order, + mode = mode ) } @@ -2231,15 +2216,13 @@ sample_smallworld <- function( loops = FALSE, multiple = FALSE ) { - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_watts_strogatz_game, - as.numeric(dim), - as.numeric(size), - as.numeric(nei), - as.numeric(p), - as.logical(loops), - as.logical(multiple) + res <- watts_strogatz_game_impl( + dim = dim, + size = size, + nei = nei, + p = p, + loops = loops, + multiple = multiple ) if (igraph_opt("add.params")) { res$name <- "Watts-Strogatz random graph" @@ -2305,14 +2288,12 @@ sample_last_cit <- function( pref = (1:(agebins + 1))^-3, directed = TRUE ) { - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_lastcit_game, - as.numeric(n), - as.numeric(edges), - as.numeric(agebins), - as.numeric(pref), - as.logical(directed) + res <- lastcit_game_impl( + nodes = n, + edges_per_node = edges, + agebins = agebins, + preference = pref, + directed = directed ) if (igraph_opt("add.params")) { res$name <- "Random citation graph based on last citation" @@ -2351,14 +2332,12 @@ sample_cit_types <- function( directed = TRUE, attr = TRUE ) { - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_cited_type_game, - as.numeric(n), - as.numeric(edges), - as.numeric(types), - as.numeric(pref), - as.logical(directed) + res <- cited_type_game_impl( + nodes = n, + types = types, + pref = pref, + edges_per_step = edges, + directed = directed ) if (attr) { V(res)$type <- types @@ -2402,14 +2381,12 @@ sample_cit_cit_types <- function( attr = TRUE ) { pref[] <- as.numeric(pref) - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_citing_cited_type_game, - as.numeric(n), - as.numeric(types), - pref, - as.numeric(edges), - as.logical(directed) + res <- citing_cited_type_game_impl( + nodes = n, + types = types, + pref = pref, + edges_per_step = edges, + directed = directed ) if (attr) { V(res)$type <- types diff --git a/R/interface.R b/R/interface.R index ef105e8921..f1f1f3b0f5 100644 --- a/R/interface.R +++ b/R/interface.R @@ -549,15 +549,15 @@ get_edge_ids <- function(graph, vp, directed = TRUE, error = FALSE) { vp <- el_to_vec(vp, call = rlang::caller_env()) - on.exit(.Call(Rx_igraph_finalizer)) - .Call( - Rx_igraph_get_eids, - graph, - as_igraph_vs(graph, vp) - 1, - as.logical(directed), - as.logical(error) - ) + - 1 + with_igraph_opt( + list(return.vs.es = FALSE), + get_eids_impl( + graph, + as_igraph_vs(graph, vp), + directed, + error + ) + ) } #' Find the edge ids based on the incident vertices of the edges diff --git a/R/make.R b/R/make.R index dba86b4f4a..a3fa21b0a6 100644 --- a/R/make.R +++ b/R/make.R @@ -83,15 +83,13 @@ graph <- function( } old_graph <- function(edges, n = max(edges), directed = TRUE) { - on.exit(.Call(Rx_igraph_finalizer)) if (missing(n) && (is.null(edges) || length(edges) == 0)) { n <- 0 } - .Call( - Rx_igraph_create, - as.numeric(edges) - 1, - as.numeric(n), - as.logical(directed) + create_impl( + edges - 1, + n, + directed ) } @@ -210,15 +208,13 @@ graph.famous <- function( } old_graph <- function(edges, n = max(edges), directed = TRUE) { - on.exit(.Call(Rx_igraph_finalizer)) if (missing(n) && (is.null(edges) || length(edges) == 0)) { n <- 0 } - .Call( - Rx_igraph_create, - as.numeric(edges) - 1, - as.numeric(n), - as.logical(directed) + create_impl( + edges - 1, + n, + directed ) } @@ -289,13 +285,11 @@ line.graph <- function(graph) { graph.ring <- function(n, directed = FALSE, mutual = FALSE, circular = TRUE) { # nocov start lifecycle::deprecate_soft("2.1.0", "graph.ring()", "make_ring()") - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_ring, - as.numeric(n), - as.logical(directed), - as.logical(mutual), - as.logical(circular) + res <- ring_impl( + n, + directed, + mutual, + circular ) if (igraph_opt("add.params")) { res$name <- "Ring graph" @@ -319,14 +313,11 @@ graph.tree <- function(n, children = 2, mode = c("out", "in", "undirected")) { # nocov start lifecycle::deprecate_soft("2.1.0", "graph.tree()", "make_tree()") mode <- igraph_match_arg(mode) - mode1 <- switch(mode, "out" = 0, "in" = 1, "undirected" = 2) - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_kary_tree, - as.numeric(n), - as.numeric(children), - as.numeric(mode1) + res <- kary_tree_impl( + n, + children, + mode ) if (igraph_opt("add.params")) { res$name <- "Tree" @@ -354,14 +345,11 @@ graph.star <- function( # nocov start lifecycle::deprecate_soft("2.1.0", "graph.star()", "make_star()") mode <- igraph_match_arg(mode) - mode1 <- switch(mode, "out" = 0, "in" = 1, "undirected" = 2, "mutual" = 3) - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_star, - as.numeric(n), - as.numeric(mode1), - as.numeric(center) - 1 + res <- star_impl( + n, + mode, + center - 1 ) if (igraph_opt("add.params")) { res$name <- switch(mode, "in" = "In-star", "out" = "Out-star", "Star") @@ -573,12 +561,10 @@ graph.full.bipartite <- function( graph.full <- function(n, directed = FALSE, loops = FALSE) { # nocov start lifecycle::deprecate_soft("2.1.0", "graph.full()", "make_full_graph()") - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_full, - as.numeric(n), - as.logical(directed), - as.logical(loops) + res <- full_impl( + n, + directed, + loops ) if (igraph_opt("add.params")) { res$name <- "Full graph" @@ -1502,15 +1488,13 @@ make_graph <- function( } old_graph <- function(edges, n = max(edges), directed = TRUE) { - on.exit(.Call(Rx_igraph_finalizer)) if (missing(n) && (is.null(edges) || length(edges) == 0)) { n <- 0 } - .Call( - Rx_igraph_create, - as.numeric(edges) - 1, - as.numeric(n), - as.logical(directed) + create_impl( + edges - 1, + n, + directed ) } @@ -1878,14 +1862,11 @@ make_star <- function( center = 1 ) { mode <- igraph_match_arg(mode) - mode1 <- switch(mode, "out" = 0, "in" = 1, "undirected" = 2, "mutual" = 3) - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_star, - as.numeric(n), - as.numeric(mode1), - as.numeric(center) - 1 + res <- star_impl( + n, + mode, + center - 1 ) if (igraph_opt("add.params")) { res$name <- switch(mode, "in" = "In-star", "out" = "Out-star", "Star") @@ -1917,12 +1898,10 @@ star <- function(n, mode = c("in", "out", "mutual", "undirected"), center = 1) { #' make_full_graph(5) #' print_all(make_full_graph(4, directed = TRUE)) make_full_graph <- function(n, directed = FALSE, loops = FALSE) { - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_full, - as.numeric(n), - as.logical(directed), - as.logical(loops) + res <- full_impl( + n, + directed, + loops ) if (igraph_opt("add.params")) { res$name <- "Full graph" @@ -2067,13 +2046,11 @@ lattice <- function( #' print_all(make_ring(10)) #' print_all(make_ring(10, directed = TRUE, mutual = TRUE)) make_ring <- function(n, directed = FALSE, mutual = FALSE, circular = TRUE) { - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_ring, - as.numeric(n), - as.logical(directed), - as.logical(mutual), - as.logical(circular) + res <- ring_impl( + n, + directed, + mutual, + circular ) if (igraph_opt("add.params")) { res$name <- "Ring graph" @@ -2191,14 +2168,11 @@ wheel <- function( #' make_tree(10, 3, mode = "undirected") make_tree <- function(n, children = 2, mode = c("out", "in", "undirected")) { mode <- igraph_match_arg(mode) - mode1 <- switch(mode, "out" = 0, "in" = 1, "undirected" = 2) - - on.exit(.Call(Rx_igraph_finalizer)) - res <- .Call( - Rx_igraph_kary_tree, - as.numeric(n), - as.numeric(children), - as.numeric(mode1) + + res <- kary_tree_impl( + n, + children, + mode ) if (igraph_opt("add.params")) { res$name <- "Tree" diff --git a/R/other.R b/R/other.R index 2db5af9584..7ea550f56e 100644 --- a/R/other.R +++ b/R/other.R @@ -132,13 +132,7 @@ sample_seq <- function(low, high, length) { cli::cli_abort("length too big for this interval") } - on.exit(.Call(Rx_igraph_finalizer)) - .Call( - Rx_igraph_random_sample, - as.numeric(low), - as.numeric(high), - as.numeric(length) - ) + random_sample_impl(low, high, length) } #' Common handler for vertex type arguments in igraph functions diff --git a/man/ba.game.Rd b/man/ba.game.Rd index bcd3f83ee7..3dc6fd7a47 100644 --- a/man/ba.game.Rd +++ b/man/ba.game.Rd @@ -23,8 +23,9 @@ ba.game( \item{power}{The power of the preferential attachment, the default is one, i.e. linear preferential attachment.} -\item{m}{Numeric constant, the number of edges to add in each time step This -argument is only used if both \code{out.dist} and \code{out.seq} are omitted +\item{m}{Numeric constant, the number of edges to add in each time step, +defaults to 1. +This argument is only used if both \code{out.dist} and \code{out.seq} are omitted or NULL.} \item{out.dist}{Numeric vector, the distribution of the number of edges to diff --git a/man/barabasi.game.Rd b/man/barabasi.game.Rd index 142526d7d7..83f4f46db9 100644 --- a/man/barabasi.game.Rd +++ b/man/barabasi.game.Rd @@ -23,8 +23,9 @@ barabasi.game( \item{power}{The power of the preferential attachment, the default is one, i.e. linear preferential attachment.} -\item{m}{Numeric constant, the number of edges to add in each time step This -argument is only used if both \code{out.dist} and \code{out.seq} are omitted +\item{m}{Numeric constant, the number of edges to add in each time step, +defaults to 1. +This argument is only used if both \code{out.dist} and \code{out.seq} are omitted or NULL.} \item{out.dist}{Numeric vector, the distribution of the number of edges to diff --git a/man/sample_pa.Rd b/man/sample_pa.Rd index c7c6608bcd..46098ad14d 100644 --- a/man/sample_pa.Rd +++ b/man/sample_pa.Rd @@ -37,8 +37,9 @@ pa( \item{power}{The power of the preferential attachment, the default is one, i.e. linear preferential attachment.} -\item{m}{Numeric constant, the number of edges to add in each time step This -argument is only used if both \code{out.dist} and \code{out.seq} are omitted +\item{m}{Numeric constant, the number of edges to add in each time step, +defaults to 1. +This argument is only used if both \code{out.dist} and \code{out.seq} are omitted or NULL.} \item{out.dist}{Numeric vector, the distribution of the number of edges to diff --git a/tests/testthat/_snaps/aaa-auto.md b/tests/testthat/_snaps/aaa-auto.md index 754b76eac8..b0266a65fc 100644 --- a/tests/testthat/_snaps/aaa-auto.md +++ b/tests/testthat/_snaps/aaa-auto.md @@ -26,7 +26,7 @@ # add_edges_impl basic Code - add_edges_impl(graph = g, edges = c(0, 1, 1, 2)) + add_edges_impl(graph = g, edges = c(1, 2, 2, 3)) Output IGRAPH D--- 3 2 -- + edges: @@ -4547,9 +4547,8 @@ Code edgelist_percolation_impl(edges = "a") Condition - Error in `edgelist_percolation_impl()`: - ! Expected numeric or integer vector, got type 16. Invalid value - Source: : + Error in `edges - 1`: + ! non-numeric argument to binary operator # is_clique_impl basic @@ -5329,7 +5328,7 @@ similarity_dice_pairs_impl(graph = g, pairs = matrix(c(1, 2, 2, 3), ncol = 2), mode = "in", loops = TRUE) Output - [1] 0.6666667 0.8000000 + [1] 0.8000000 0.6666667 # similarity_dice_pairs_impl errors @@ -5428,7 +5427,7 @@ similarity_jaccard_pairs_impl(graph = g, pairs = matrix(c(1, 2, 2, 3), ncol = 2), mode = "in", loops = TRUE) Output - [1] 0.5000000 0.6666667 + [1] 0.6666667 0.5000000 # similarity_jaccard_pairs_impl errors diff --git a/tests/testthat/_snaps/conversion.md b/tests/testthat/_snaps/conversion.md index 2f981abe68..a7afcea593 100644 --- a/tests/testthat/_snaps/conversion.md +++ b/tests/testthat/_snaps/conversion.md @@ -95,3 +95,318 @@ Error in `graph_from_edgelist()`: ! Cannot create a graph object because the edgelist contains NAs. +# as_adjacency_matrix() comprehensive snapshot tests + + Code + as_adjacency_matrix(g_dir_unwt, sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 1 . + [2,] . 1 1 + [3,] 1 . . + +--- + + Code + as_adjacency_matrix(g_dir_unwt, type = "upper", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 1 . + [2,] . 1 1 + [3,] 1 . . + +--- + + Code + as_adjacency_matrix(g_dir_unwt, type = "lower", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 1 . + [2,] . 1 1 + [3,] 1 . . + +--- + + Code + as_adjacency_matrix(g_dir_unwt, sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0 1 0 + [2,] 0 1 1 + [3,] 1 0 0 + +--- + + Code + as_adjacency_matrix(g_dir_unwt, type = "upper", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0 1 0 + [2,] 0 1 1 + [3,] 1 0 0 + +--- + + Code + as_adjacency_matrix(g_dir_unwt, type = "lower", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0 1 0 + [2,] 0 1 1 + [3,] 1 0 0 + +--- + + Code + as_adjacency_matrix(g_dir_wt, attr = "weight", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 1.5 . + [2,] . 0.5 2.3 + [3,] 3.7 . . + +--- + + Code + as_adjacency_matrix(g_dir_wt, attr = "weight", type = "upper", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 1.5 . + [2,] . 0.5 2.3 + [3,] 3.7 . . + +--- + + Code + as_adjacency_matrix(g_dir_wt, attr = "weight", type = "lower", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 1.5 . + [2,] . 0.5 2.3 + [3,] 3.7 . . + +--- + + Code + as_adjacency_matrix(g_dir_wt, attr = "weight", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0.0 1.5 0.0 + [2,] 0.0 0.5 2.3 + [3,] 3.7 0.0 0.0 + +--- + + Code + as_adjacency_matrix(g_dir_wt, attr = "weight", type = "upper", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0.0 1.5 0.0 + [2,] 0.0 0.5 2.3 + [3,] 3.7 0.0 0.0 + +--- + + Code + as_adjacency_matrix(g_dir_wt, attr = "weight", type = "lower", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0.0 1.5 0.0 + [2,] 0.0 0.5 2.3 + [3,] 3.7 0.0 0.0 + +--- + + Code + as_adjacency_matrix(g_undir_unwt, sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 1 1 + [2,] 1 . 1 + [3,] 1 1 . + +--- + + Code + as_adjacency_matrix(g_undir_unwt, type = "upper", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 1 1 + [2,] . . 1 + [3,] . . . + +--- + + Code + as_adjacency_matrix(g_undir_unwt, type = "lower", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . . . + [2,] 1 . . + [3,] 1 1 . + +--- + + Code + as_adjacency_matrix(g_undir_unwt, type = "both", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 1 1 + [2,] 1 . 1 + [3,] 1 1 . + +--- + + Code + as_adjacency_matrix(g_undir_unwt, sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0 1 1 + [2,] 1 0 1 + [3,] 1 1 0 + +--- + + Code + as_adjacency_matrix(g_undir_unwt, type = "upper", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0 1 1 + [2,] 0 0 1 + [3,] 0 0 0 + +--- + + Code + as_adjacency_matrix(g_undir_unwt, type = "lower", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0 0 0 + [2,] 1 0 0 + [3,] 1 1 0 + +--- + + Code + as_adjacency_matrix(g_undir_unwt, type = "both", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0 1 1 + [2,] 1 0 1 + [3,] 1 1 0 + +--- + + Code + as_adjacency_matrix(g_undir_wt, attr = "weight", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 2.1 3.2 + [2,] 2.1 . 4.3 + [3,] 3.2 4.3 . + +--- + + Code + as_adjacency_matrix(g_undir_wt, attr = "weight", type = "upper", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 2.1 3.2 + [2,] . . 4.3 + [3,] . . . + +--- + + Code + as_adjacency_matrix(g_undir_wt, attr = "weight", type = "lower", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . . . + [2,] 2.1 . . + [3,] 3.2 4.3 . + +--- + + Code + as_adjacency_matrix(g_undir_wt, attr = "weight", type = "both", sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + + [1,] . 2.1 3.2 + [2,] 2.1 . 4.3 + [3,] 3.2 4.3 . + +--- + + Code + as_adjacency_matrix(g_undir_wt, attr = "weight", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0.0 2.1 3.2 + [2,] 2.1 0.0 4.3 + [3,] 3.2 4.3 0.0 + +--- + + Code + as_adjacency_matrix(g_undir_wt, attr = "weight", type = "upper", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0 2.1 3.2 + [2,] 0 0.0 4.3 + [3,] 0 0.0 0.0 + +--- + + Code + as_adjacency_matrix(g_undir_wt, attr = "weight", type = "lower", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0.0 0.0 0 + [2,] 2.1 0.0 0 + [3,] 3.2 4.3 0 + +--- + + Code + as_adjacency_matrix(g_undir_wt, attr = "weight", type = "both", sparse = FALSE) + Output + [,1] [,2] [,3] + [1,] 0.0 2.1 3.2 + [2,] 2.1 0.0 4.3 + [3,] 3.2 4.3 0.0 + +--- + + Code + as_adjacency_matrix(g_named, sparse = TRUE) + Output + 3 x 3 sparse Matrix of class "dgCMatrix" + A B C + A . 1 . + B . 1 1 + C 1 . . + +--- + + Code + as_adjacency_matrix(g_named, sparse = FALSE) + Output + A B C + A 0 1 0 + B 0 1 1 + C 1 0 0 + diff --git a/tests/testthat/_snaps/games.md b/tests/testthat/_snaps/games.md index 8b30cb2190..56ba3f0533 100644 --- a/tests/testthat/_snaps/games.md +++ b/tests/testthat/_snaps/games.md @@ -3,7 +3,7 @@ Code sample_degseq(exponential_degrees, method = "vl") Condition - Error in `sample_degseq()`: + Error in `degree_sequence_game_impl()`: ! Cannot make a connected graph from the given degree sequence. Invalid value Source: : @@ -12,7 +12,7 @@ Code sample_degseq(powerlaw_degrees, method = "vl") Condition - Error in `sample_degseq()`: + Error in `degree_sequence_game_impl()`: ! Cannot realize the given degree sequence as an undirected, simple graph. Invalid value Source: : diff --git a/tests/testthat/test-aaa-auto.R b/tests/testthat/test-aaa-auto.R index 466ef44604..ce6b4f6fcf 100644 --- a/tests/testthat/test-aaa-auto.R +++ b/tests/testthat/test-aaa-auto.R @@ -57,13 +57,13 @@ test_that("add_edges_impl basic", { expect_snapshot(add_edges_impl( graph = g, - edges = c(0, 1, 1, 2) + edges = c(1, 2, 2, 3) )) # Structured tests result <- add_edges_impl( graph = g, - edges = c(0, 1, 1, 2) + edges = c(1, 2, 2, 3) ) expect_s3_class(result, "igraph") expect_equal(vcount(result), 3) @@ -11761,8 +11761,8 @@ test_that("union_many_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g1 <- empty_impl(n = 3) - g2 <- add_edges_impl(g1, c(0, 1, 1, 2)) - g3 <- add_edges_impl(g1, c(0, 2)) + g2 <- add_edges_impl(g1, c(0, 1, 1, 2) + 1) + g3 <- add_edges_impl(g1, c(0, 2) + 1) expect_snapshot(union_many_impl( graphs = list(g1, g2, g3) @@ -11779,9 +11779,9 @@ test_that("union_many_impl basic", { test_that("intersection_many_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) - g1 <- add_edges_impl(empty_impl(n = 3), c(0, 1, 1, 2, 0, 2)) - g2 <- add_edges_impl(empty_impl(n = 3), c(0, 1, 1, 2)) - g3 <- add_edges_impl(empty_impl(n = 3), c(0, 1)) + g1 <- add_edges_impl(empty_impl(n = 3), c(0, 1, 1, 2, 0, 2) + 1) + g2 <- add_edges_impl(empty_impl(n = 3), c(0, 1, 1, 2) + 1) + g3 <- add_edges_impl(empty_impl(n = 3), c(0, 1) + 1) expect_snapshot(intersection_many_impl( graphs = list(g1, g2, g3) diff --git a/tests/testthat/test-conversion.R b/tests/testthat/test-conversion.R index 65a2858fc6..aa767e1568 100644 --- a/tests/testthat/test-conversion.R +++ b/tests/testthat/test-conversion.R @@ -703,3 +703,166 @@ test_that("graph_from_data_frame works with factors", { expect_true(is.factor(V(g)$gender)) expect_true(is.factor(g_actors$gender)) }) + +test_that("as_adjacency_matrix() comprehensive snapshot tests", { + # Directed, unweighted, sparse + g_dir_unwt <- make_graph(c(1, 2, 2, 3, 3, 1, 2, 2), directed = TRUE) + expect_snapshot(as_adjacency_matrix(g_dir_unwt, sparse = TRUE)) + expect_snapshot(as_adjacency_matrix( + g_dir_unwt, + type = "upper", + sparse = TRUE + )) + expect_snapshot(as_adjacency_matrix( + g_dir_unwt, + type = "lower", + sparse = TRUE + )) + + # Directed, unweighted, dense + expect_snapshot(as_adjacency_matrix(g_dir_unwt, sparse = FALSE)) + expect_snapshot(as_adjacency_matrix( + g_dir_unwt, + type = "upper", + sparse = FALSE + )) + expect_snapshot(as_adjacency_matrix( + g_dir_unwt, + type = "lower", + sparse = FALSE + )) + + # Directed, weighted, sparse + g_dir_wt <- g_dir_unwt + E(g_dir_wt)$weight <- c(1.5, 2.3, 3.7, 0.5) + expect_snapshot(as_adjacency_matrix(g_dir_wt, attr = "weight", sparse = TRUE)) + expect_snapshot(as_adjacency_matrix( + g_dir_wt, + attr = "weight", + type = "upper", + sparse = TRUE + )) + expect_snapshot(as_adjacency_matrix( + g_dir_wt, + attr = "weight", + type = "lower", + sparse = TRUE + )) + + # Directed, weighted, dense + expect_snapshot(as_adjacency_matrix( + g_dir_wt, + attr = "weight", + sparse = FALSE + )) + expect_snapshot(as_adjacency_matrix( + g_dir_wt, + attr = "weight", + type = "upper", + sparse = FALSE + )) + expect_snapshot(as_adjacency_matrix( + g_dir_wt, + attr = "weight", + type = "lower", + sparse = FALSE + )) + + # Undirected, unweighted, sparse + g_undir_unwt <- as_undirected( + make_graph(c(1, 2, 2, 3, 3, 1)), + mode = "collapse" + ) + expect_snapshot(as_adjacency_matrix(g_undir_unwt, sparse = TRUE)) + expect_snapshot(as_adjacency_matrix( + g_undir_unwt, + type = "upper", + sparse = TRUE + )) + expect_snapshot(as_adjacency_matrix( + g_undir_unwt, + type = "lower", + sparse = TRUE + )) + expect_snapshot(as_adjacency_matrix( + g_undir_unwt, + type = "both", + sparse = TRUE + )) + + # Undirected, unweighted, dense + expect_snapshot(as_adjacency_matrix(g_undir_unwt, sparse = FALSE)) + expect_snapshot(as_adjacency_matrix( + g_undir_unwt, + type = "upper", + sparse = FALSE + )) + expect_snapshot(as_adjacency_matrix( + g_undir_unwt, + type = "lower", + sparse = FALSE + )) + expect_snapshot(as_adjacency_matrix( + g_undir_unwt, + type = "both", + sparse = FALSE + )) + + # Undirected, weighted, sparse + g_undir_wt <- g_undir_unwt + E(g_undir_wt)$weight <- c(2.1, 3.2, 4.3) + expect_snapshot(as_adjacency_matrix( + g_undir_wt, + attr = "weight", + sparse = TRUE + )) + expect_snapshot(as_adjacency_matrix( + g_undir_wt, + attr = "weight", + type = "upper", + sparse = TRUE + )) + expect_snapshot(as_adjacency_matrix( + g_undir_wt, + attr = "weight", + type = "lower", + sparse = TRUE + )) + expect_snapshot(as_adjacency_matrix( + g_undir_wt, + attr = "weight", + type = "both", + sparse = TRUE + )) + + # Undirected, weighted, dense + expect_snapshot(as_adjacency_matrix( + g_undir_wt, + attr = "weight", + sparse = FALSE + )) + expect_snapshot(as_adjacency_matrix( + g_undir_wt, + attr = "weight", + type = "upper", + sparse = FALSE + )) + expect_snapshot(as_adjacency_matrix( + g_undir_wt, + attr = "weight", + type = "lower", + sparse = FALSE + )) + expect_snapshot(as_adjacency_matrix( + g_undir_wt, + attr = "weight", + type = "both", + sparse = FALSE + )) + + # With vertex names + g_named <- g_dir_unwt + V(g_named)$name <- c("A", "B", "C") + expect_snapshot(as_adjacency_matrix(g_named, sparse = TRUE)) + expect_snapshot(as_adjacency_matrix(g_named, sparse = FALSE)) +}) diff --git a/tests/testthat/test-interface.R b/tests/testthat/test-interface.R index ff287fbb0a..e08493d979 100644 --- a/tests/testthat/test-interface.R +++ b/tests/testthat/test-interface.R @@ -248,3 +248,19 @@ test_that("invalidate_cache errors on invalid input", { expect_error(invalidate_cache("not a graph")) expect_error(invalidate_cache(123)) }) + +test_that("get_edge_ids() returns numeric vector, not igraph.es", { + g <- make_full_graph(10) + mat <- matrix(c(1, 2, 1, 3, 1, 4), 3, 2, byrow = TRUE) + result <- get_edge_ids(g, mat) + expect_true(is.numeric(result)) + expect_false(inherits(result, "igraph.es")) + expect_equal(result, c(1, 2, 3)) +}) + +test_that("get_edge_ids() returns 0 for missing edges when error=FALSE", { + g <- make_empty_graph(10) + result <- get_edge_ids(g, c(1, 2), error = FALSE) + expect_equal(result, 0) + expect_true(is.numeric(result)) +}) diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index 018d397c6f..c381baaf85 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -519,6 +519,14 @@ igraph_full_bipartite: igraph_decompose: +####################################### +# Percolation +####################################### + +igraph_edgelist_percolation: + # VERTEX_INDEX_PAIRS has a dependency that we don't have here + PARAMS: INDEX_PAIRS edges, OUT VECTOR_INT giant_size, OUT VECTOR_INT vertex_count + ####################################### # Cliques ####################################### diff --git a/tools/stimulus/types-RC.yaml b/tools/stimulus/types-RC.yaml index 1fcb29b8f5..7c362dba58 100644 --- a/tools/stimulus/types-RC.yaml +++ b/tools/stimulus/types-RC.yaml @@ -627,6 +627,18 @@ VERTEX_INDEX_PAIRS: igraph_vector_int_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); +INDEX_PAIRS: + CALL: '&%C%' + CTYPE: igraph_vector_int_t + INCONV: + IN: |- + Rz_SEXP_to_vector_int_copy(%I%, &%C%); + IGRAPH_FINALLY(igraph_vector_int_destroy, &%C%); + OUTCONV: + IN: |- + igraph_vector_int_destroy(&%C%); + IGRAPH_FINALLY_CLEAN(1); + EDGE_INDICES: CALL: '&%C%' CTYPE: igraph_vector_int_t diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index 73ff47ae80..cb52f5cd26 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -276,6 +276,13 @@ VERTEX_INDICES_PV: %I% <- create_vs(%I1%, %I%) } +VERTEX_INDEX_PAIRS: + CALL: '%I% - 1' + INCONV: '%I% <- as_igraph_vs(%I1%, %I%)' + +INDEX_PAIRS: + CALL: '%I% - 1' + EDGE_INDICES: CALL: '%I% - 1' DEFAULT: