diff --git a/R/aaa-auto.R b/R/aaa-auto.R index e962b0800fa..f4387d64142 100644 --- a/R/aaa-auto.R +++ b/R/aaa-auto.R @@ -35,14 +35,14 @@ copy_impl <- function(from) { res } -delete_vertices_idx_impl <- function(graph, vertices) { +delete_vertices_map_impl <- function(graph, vertices) { # Argument checks ensure_igraph(graph) vertices <- as_igraph_vs(graph, vertices) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_delete_vertices_idx, graph, vertices-1) + res <- .Call(R_igraph_delete_vertices_map, graph, vertices-1) res } @@ -750,7 +750,7 @@ distances_bellman_ford_impl <- function(graph, from=V(graph), to=V(graph), weigh res } -distances_johnson_impl <- function(graph, from=V(graph), to=V(graph), weights) { +distances_johnson_impl <- function(graph, from=V(graph), to=V(graph), weights=NULL, mode=c("out", "in", "all", "total")) { # Argument checks ensure_igraph(graph) from <- as_igraph_vs(graph, from) @@ -763,10 +763,11 @@ distances_johnson_impl <- function(graph, from=V(graph), to=V(graph), weights) { } else { weights <- NULL } + mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_distances_johnson, graph, from-1, to-1, weights) + res <- .Call(R_igraph_distances_johnson, graph, from-1, to-1, weights, mode) res } @@ -1024,7 +1025,9 @@ edge_betweenness_subset_impl <- function(graph, eids=E(graph), directed=TRUE, so on.exit( .Call(R_igraph_finalizer) ) # Function call res <- .Call(R_igraph_edge_betweenness_subset, graph, eids-1, directed, sources-1, targets-1, weights) - + if (igraph_opt("add.vertex.names") && is_named(graph)) { + names(res) <- vertex_attr(graph, "name", V(graph)) + } res } @@ -2472,16 +2475,17 @@ layout_umap_compute_weights_impl <- function(graph, distances, weights) { res } -similarity_dice_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), loops=FALSE) { +similarity_dice_impl <- function(graph, vit.from=V(graph), vit.to=V(graph), mode=c("all", "out", "in", "total"), loops=FALSE) { # Argument checks ensure_igraph(graph) - vids <- as_igraph_vs(graph, vids) + vit.from <- as_igraph_vs(graph, vit.from) + vit.to <- as_igraph_vs(graph, vit.to) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) loops <- as.logical(loops) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_similarity_dice, graph, vids-1, mode, loops) + res <- .Call(R_igraph_similarity_dice, graph, vit.from-1, vit.to-1, mode, loops) res } @@ -2526,16 +2530,17 @@ similarity_inverse_log_weighted_impl <- function(graph, vids=V(graph), mode=c("a res } -similarity_jaccard_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total"), loops=FALSE) { +similarity_jaccard_impl <- function(graph, vit.from=V(graph), vit.to=V(graph), mode=c("all", "out", "in", "total"), loops=FALSE) { # Argument checks ensure_igraph(graph) - vids <- as_igraph_vs(graph, vids) + vit.from <- as_igraph_vs(graph, vit.from) + vit.to <- as_igraph_vs(graph, vit.to) mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L) loops <- as.logical(loops) on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_similarity_jaccard, graph, vids-1, mode, loops) + res <- .Call(R_igraph_similarity_jaccard, graph, vit.from-1, vit.to-1, mode, loops) res } @@ -3085,6 +3090,50 @@ isomorphic_impl <- function(graph1, graph2) { res } +automorphism_group_impl <- function(graph, colors=NULL) { + # Argument checks + ensure_igraph(graph) + if (missing(colors)) { + if ("color" %in% vertex_attr_names(graph)) { + colors <- V(graph)$color + } else { + colors <- NULL + } + } + if (!is.null(colors)) { + colors <- as.numeric(colors)-1 + } + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_automorphism_group, graph, colors) + if (igraph_opt("return.vs.es")) { + res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph)) + } + res +} + +count_automorphisms_impl <- function(graph, colors=NULL) { + # Argument checks + ensure_igraph(graph) + if (missing(colors)) { + if ("color" %in% vertex_attr_names(graph)) { + colors <- V(graph)$color + } else { + colors <- NULL + } + } + if (!is.null(colors)) { + colors <- as.numeric(colors)-1 + } + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_count_automorphisms, graph, colors) + + res +} + isoclass_create_impl <- function(size, number, directed=TRUE) { # Argument checks size <- as.numeric(size) @@ -3318,7 +3367,28 @@ count_subisomorphisms_vf2_impl <- function(graph1, graph2, vertex.color1, vertex res } -canonical_permutation_impl <- function(graph, colors=NULL, sh=c("fm", "f", "fs", "fl", "flm", "fsm")) { +canonical_permutation_impl <- function(graph, colors=NULL) { + # Argument checks + ensure_igraph(graph) + if (missing(colors)) { + if ("color" %in% vertex_attr_names(graph)) { + colors <- V(graph)$color + } else { + colors <- NULL + } + } + if (!is.null(colors)) { + colors <- as.numeric(colors)-1 + } + + on.exit( .Call(R_igraph_finalizer) ) + # Function call + res <- .Call(R_igraph_canonical_permutation, graph, colors) + + res +} + +canonical_permutation_bliss_impl <- function(graph, colors=NULL, sh=c("fm", "f", "fs", "fl", "flm", "fsm")) { # Argument checks ensure_igraph(graph) if (missing(colors)) { @@ -3335,7 +3405,7 @@ canonical_permutation_impl <- function(graph, colors=NULL, sh=c("fm", "f", "fs", on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_canonical_permutation, graph, colors, sh) + res <- .Call(R_igraph_canonical_permutation_bliss, graph, colors, sh) res } @@ -3385,7 +3455,7 @@ isomorphic_bliss_impl <- function(graph1, graph2, colors1=NULL, colors2=NULL, sh res } -count_automorphisms_impl <- function(graph, colors=NULL, sh=c("fm", "f", "fs", "fl", "flm", "fsm")) { +count_automorphisms_bliss_impl <- function(graph, colors=NULL, sh=c("fm", "f", "fs", "fl", "flm", "fsm")) { # Argument checks ensure_igraph(graph) if (missing(colors)) { @@ -3402,12 +3472,12 @@ count_automorphisms_impl <- function(graph, colors=NULL, sh=c("fm", "f", "fs", " on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_count_automorphisms, graph, colors, sh) + res <- .Call(R_igraph_count_automorphisms_bliss, graph, colors, sh) res } -automorphism_group_impl <- function(graph, colors=NULL, sh=c("fm", "f", "fs", "fl", "flm", "fsm"), details=FALSE) { +automorphism_group_bliss_impl <- function(graph, colors=NULL, sh=c("fm", "f", "fs", "fl", "flm", "fsm"), details=FALSE) { # Argument checks ensure_igraph(graph) if (missing(colors)) { @@ -3424,7 +3494,7 @@ automorphism_group_impl <- function(graph, colors=NULL, sh=c("fm", "f", "fs", "f on.exit( .Call(R_igraph_finalizer) ) # Function call - res <- .Call(R_igraph_automorphism_group, graph, colors, sh) + res <- .Call(R_igraph_automorphism_group_bliss, graph, colors, sh) if (igraph_opt("return.vs.es")) { res$generators <- lapply(res$generators, unsafe_create_vs, graph = graph, verts = V(graph)) } diff --git a/R/games.R b/R/games.R index b76b6f1e624..df50b5ff560 100644 --- a/R/games.R +++ b/R/games.R @@ -1756,7 +1756,7 @@ sample_bipartite <- function(n1, n2, type = c("gnp", "gnm"), p, m, res$name <- "Bipartite Gnp random graph" res$p <- p } else if (type == "gnm") { - res <- .Call(R_igraph_bipartite_game_gnm, n1, n2, m, directed, mode) + res <- .Call(R_igraph_bipartite_game_gnm, n1, n2, m, directed, mode, multiple = FALSE) res <- set_vertex_attr(res$graph, "type", value = res$types) res$name <- "Bipartite Gnm random graph" res$m <- m diff --git a/src/cpp11.cpp b/src/cpp11.cpp index ef691f87be1..99d4cbbb5d9 100644 --- a/src/cpp11.cpp +++ b/src/cpp11.cpp @@ -48,7 +48,8 @@ extern SEXP R_igraph_assortativity_nominal(void *, void *, void *, void *); extern SEXP R_igraph_asymmetric_preference_game(void *, void *, void *, void *, void *, void *); extern SEXP R_igraph_atlas(void *); extern SEXP R_igraph_authority_score(void *, void *, void *, void *); -extern SEXP R_igraph_automorphism_group(void *, void *, void *); +extern SEXP R_igraph_automorphism_group(void *, void *); +extern SEXP R_igraph_automorphism_group_bliss(void *, void *, void *); extern SEXP R_igraph_average_local_efficiency(void *, void *, void *, void *); extern SEXP R_igraph_average_path_length_dijkstra(void *, void *, void *, void *); extern SEXP R_igraph_avg_nearest_neighbor_degree(void *, void *, void *, void *, void *); @@ -62,13 +63,14 @@ extern SEXP R_igraph_biadjacency(void *, void *, void *, void *); extern SEXP R_igraph_bibcoupling(void *, void *); extern SEXP R_igraph_biconnected_components(void *); extern SEXP R_igraph_bipartite_game(void *, void *, void *, void *, void *, void *, void *); -extern SEXP R_igraph_bipartite_game_gnm(void *, void *, void *, void *, void *); +extern SEXP R_igraph_bipartite_game_gnm(void *, void *, void *, void *, void *, void *); extern SEXP R_igraph_bipartite_game_gnp(void *, void *, void *, void *, void *); extern SEXP R_igraph_bipartite_projection(void *, void *, void *, void *); extern SEXP R_igraph_bipartite_projection_size(void *, void *); extern SEXP R_igraph_bridges(void *); extern SEXP R_igraph_callaway_traits_game(void *, void *, void *, void *, void *, void *); -extern SEXP R_igraph_canonical_permutation(void *, void *, void *); +extern SEXP R_igraph_canonical_permutation(void *, void *); +extern SEXP R_igraph_canonical_permutation_bliss(void *, void *, void *); extern SEXP R_igraph_centralization(void *, void *, void *); extern SEXP R_igraph_centralization_betweenness(void *, void *, void *); extern SEXP R_igraph_centralization_betweenness_tmax(void *, void *, void *); @@ -113,7 +115,8 @@ extern SEXP R_igraph_copy_to(void *); extern SEXP R_igraph_coreness(void *, void *); extern SEXP R_igraph_correlated_game(void *, void *, void *, void *); extern SEXP R_igraph_correlated_pair_game(void *, void *, void *, void *, void *); -extern SEXP R_igraph_count_automorphisms(void *, void *, void *); +extern SEXP R_igraph_count_automorphisms(void *, void *); +extern SEXP R_igraph_count_automorphisms_bliss(void *, void *, void *); extern SEXP R_igraph_count_isomorphisms_vf2(void *, void *, void *, void *, void *, void *); extern SEXP R_igraph_count_multiple(void *, void *); extern SEXP R_igraph_count_subisomorphisms_vf2(void *, void *, void *, void *, void *, void *); @@ -126,7 +129,7 @@ extern SEXP R_igraph_degree_correlation_vector(void *, void *, void *, void *, v extern SEXP R_igraph_degree_sequence_game(void *, void *, void *); extern SEXP R_igraph_delete_edges(void *, void *); extern SEXP R_igraph_delete_vertices(void *, void *); -extern SEXP R_igraph_delete_vertices_idx(void *, void *); +extern SEXP R_igraph_delete_vertices_map(void *, void *); extern SEXP R_igraph_density(void *, void *); extern SEXP R_igraph_deterministic_optimal_imitation(void *, void *, void *, void *, void *, void *); extern SEXP R_igraph_dfs(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); @@ -140,7 +143,7 @@ extern SEXP R_igraph_distances_cutoff(void *, void *, void *, void *, void *); extern SEXP R_igraph_distances_dijkstra(void *, void *, void *, void *, void *); extern SEXP R_igraph_distances_dijkstra_cutoff(void *, void *, void *, void *, void *, void *); extern SEXP R_igraph_distances_floyd_warshall(void *, void *, void *, void *, void *, void *); -extern SEXP R_igraph_distances_johnson(void *, void *, void *, void *); +extern SEXP R_igraph_distances_johnson(void *, void *, void *, void *, void *); extern SEXP R_igraph_diversity(void *, void *, void *); extern SEXP R_igraph_dominator_tree(void *, void *, void *); extern SEXP R_igraph_dot_product_game(void *, void *); @@ -396,11 +399,11 @@ extern SEXP R_igraph_sample_sphere_volume(void *, void *, void *, void *); extern SEXP R_igraph_sbm_game(void *, void *, void *, void *, void *); extern SEXP R_igraph_set_verbose(void *); extern SEXP R_igraph_shortest_paths(void *, void *, void *, void *, void *, void *); -extern SEXP R_igraph_similarity_dice(void *, void *, void *, void *); +extern SEXP R_igraph_similarity_dice(void *, void *, void *, void *, void *); extern SEXP R_igraph_similarity_dice_es(void *, void *, void *, void *); extern SEXP R_igraph_similarity_dice_pairs(void *, void *, void *, void *); extern SEXP R_igraph_similarity_inverse_log_weighted(void *, void *, void *); -extern SEXP R_igraph_similarity_jaccard(void *, void *, void *, void *); +extern SEXP R_igraph_similarity_jaccard(void *, void *, void *, void *, void *); extern SEXP R_igraph_similarity_jaccard_es(void *, void *, void *, void *); extern SEXP R_igraph_similarity_jaccard_pairs(void *, void *, void *, void *); extern SEXP R_igraph_simple_interconnected_islands_game(void *, void *, void *, void *); @@ -507,7 +510,8 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_asymmetric_preference_game", (DL_FUNC) &R_igraph_asymmetric_preference_game, 6}, {"R_igraph_atlas", (DL_FUNC) &R_igraph_atlas, 1}, {"R_igraph_authority_score", (DL_FUNC) &R_igraph_authority_score, 4}, - {"R_igraph_automorphism_group", (DL_FUNC) &R_igraph_automorphism_group, 3}, + {"R_igraph_automorphism_group", (DL_FUNC) &R_igraph_automorphism_group, 2}, + {"R_igraph_automorphism_group_bliss", (DL_FUNC) &R_igraph_automorphism_group_bliss, 3}, {"R_igraph_average_local_efficiency", (DL_FUNC) &R_igraph_average_local_efficiency, 4}, {"R_igraph_average_path_length_dijkstra", (DL_FUNC) &R_igraph_average_path_length_dijkstra, 4}, {"R_igraph_avg_nearest_neighbor_degree", (DL_FUNC) &R_igraph_avg_nearest_neighbor_degree, 5}, @@ -521,13 +525,14 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_bibcoupling", (DL_FUNC) &R_igraph_bibcoupling, 2}, {"R_igraph_biconnected_components", (DL_FUNC) &R_igraph_biconnected_components, 1}, {"R_igraph_bipartite_game", (DL_FUNC) &R_igraph_bipartite_game, 7}, - {"R_igraph_bipartite_game_gnm", (DL_FUNC) &R_igraph_bipartite_game_gnm, 5}, + {"R_igraph_bipartite_game_gnm", (DL_FUNC) &R_igraph_bipartite_game_gnm, 6}, {"R_igraph_bipartite_game_gnp", (DL_FUNC) &R_igraph_bipartite_game_gnp, 5}, {"R_igraph_bipartite_projection", (DL_FUNC) &R_igraph_bipartite_projection, 4}, {"R_igraph_bipartite_projection_size", (DL_FUNC) &R_igraph_bipartite_projection_size, 2}, {"R_igraph_bridges", (DL_FUNC) &R_igraph_bridges, 1}, {"R_igraph_callaway_traits_game", (DL_FUNC) &R_igraph_callaway_traits_game, 6}, - {"R_igraph_canonical_permutation", (DL_FUNC) &R_igraph_canonical_permutation, 3}, + {"R_igraph_canonical_permutation", (DL_FUNC) &R_igraph_canonical_permutation, 2}, + {"R_igraph_canonical_permutation_bliss", (DL_FUNC) &R_igraph_canonical_permutation_bliss, 3}, {"R_igraph_centralization", (DL_FUNC) &R_igraph_centralization, 3}, {"R_igraph_centralization_betweenness", (DL_FUNC) &R_igraph_centralization_betweenness, 3}, {"R_igraph_centralization_betweenness_tmax", (DL_FUNC) &R_igraph_centralization_betweenness_tmax, 3}, @@ -572,7 +577,8 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_coreness", (DL_FUNC) &R_igraph_coreness, 2}, {"R_igraph_correlated_game", (DL_FUNC) &R_igraph_correlated_game, 4}, {"R_igraph_correlated_pair_game", (DL_FUNC) &R_igraph_correlated_pair_game, 5}, - {"R_igraph_count_automorphisms", (DL_FUNC) &R_igraph_count_automorphisms, 3}, + {"R_igraph_count_automorphisms", (DL_FUNC) &R_igraph_count_automorphisms, 2}, + {"R_igraph_count_automorphisms_bliss", (DL_FUNC) &R_igraph_count_automorphisms_bliss, 3}, {"R_igraph_count_isomorphisms_vf2", (DL_FUNC) &R_igraph_count_isomorphisms_vf2, 6}, {"R_igraph_count_multiple", (DL_FUNC) &R_igraph_count_multiple, 2}, {"R_igraph_count_subisomorphisms_vf2", (DL_FUNC) &R_igraph_count_subisomorphisms_vf2, 6}, @@ -585,7 +591,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_degree_sequence_game", (DL_FUNC) &R_igraph_degree_sequence_game, 3}, {"R_igraph_delete_edges", (DL_FUNC) &R_igraph_delete_edges, 2}, {"R_igraph_delete_vertices", (DL_FUNC) &R_igraph_delete_vertices, 2}, - {"R_igraph_delete_vertices_idx", (DL_FUNC) &R_igraph_delete_vertices_idx, 2}, + {"R_igraph_delete_vertices_map", (DL_FUNC) &R_igraph_delete_vertices_map, 2}, {"R_igraph_density", (DL_FUNC) &R_igraph_density, 2}, {"R_igraph_deterministic_optimal_imitation", (DL_FUNC) &R_igraph_deterministic_optimal_imitation, 6}, {"R_igraph_dfs", (DL_FUNC) &R_igraph_dfs, 12}, @@ -599,7 +605,7 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_distances_dijkstra", (DL_FUNC) &R_igraph_distances_dijkstra, 5}, {"R_igraph_distances_dijkstra_cutoff", (DL_FUNC) &R_igraph_distances_dijkstra_cutoff, 6}, {"R_igraph_distances_floyd_warshall", (DL_FUNC) &R_igraph_distances_floyd_warshall, 6}, - {"R_igraph_distances_johnson", (DL_FUNC) &R_igraph_distances_johnson, 4}, + {"R_igraph_distances_johnson", (DL_FUNC) &R_igraph_distances_johnson, 5}, {"R_igraph_diversity", (DL_FUNC) &R_igraph_diversity, 3}, {"R_igraph_dominator_tree", (DL_FUNC) &R_igraph_dominator_tree, 3}, {"R_igraph_dot_product_game", (DL_FUNC) &R_igraph_dot_product_game, 2}, @@ -855,11 +861,11 @@ static const R_CallMethodDef CallEntries[] = { {"R_igraph_sbm_game", (DL_FUNC) &R_igraph_sbm_game, 5}, {"R_igraph_set_verbose", (DL_FUNC) &R_igraph_set_verbose, 1}, {"R_igraph_shortest_paths", (DL_FUNC) &R_igraph_shortest_paths, 6}, - {"R_igraph_similarity_dice", (DL_FUNC) &R_igraph_similarity_dice, 4}, + {"R_igraph_similarity_dice", (DL_FUNC) &R_igraph_similarity_dice, 5}, {"R_igraph_similarity_dice_es", (DL_FUNC) &R_igraph_similarity_dice_es, 4}, {"R_igraph_similarity_dice_pairs", (DL_FUNC) &R_igraph_similarity_dice_pairs, 4}, {"R_igraph_similarity_inverse_log_weighted", (DL_FUNC) &R_igraph_similarity_inverse_log_weighted, 3}, - {"R_igraph_similarity_jaccard", (DL_FUNC) &R_igraph_similarity_jaccard, 4}, + {"R_igraph_similarity_jaccard", (DL_FUNC) &R_igraph_similarity_jaccard, 5}, {"R_igraph_similarity_jaccard_es", (DL_FUNC) &R_igraph_similarity_jaccard_es, 4}, {"R_igraph_similarity_jaccard_pairs", (DL_FUNC) &R_igraph_similarity_jaccard_pairs, 4}, {"R_igraph_simple_interconnected_islands_game", (DL_FUNC) &R_igraph_simple_interconnected_islands_game, 4}, diff --git a/src/rinterface.c b/src/rinterface.c index c531e534444..595d8c3ad32 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -72,6 +72,7 @@ SEXP R_igraph_add_edges(SEXP graph, SEXP edges) { R_SEXP_to_igraph_copy(graph, &c_graph); IGRAPH_FINALLY(igraph_destroy, &c_graph); R_SEXP_to_vector_int_copy(edges, &c_edges); + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_edges); /* Call igraph */ IGRAPH_R_CHECK(igraph_add_edges(&c_graph, &c_edges, 0)); @@ -79,6 +80,8 @@ SEXP R_igraph_add_edges(SEXP graph, SEXP edges) { PROTECT(graph=R_igraph_to_SEXP(&c_graph)); IGRAPH_I_DESTROY(&c_graph); IGRAPH_FINALLY_CLEAN(1); + igraph_vector_int_destroy(&c_edges); + IGRAPH_FINALLY_CLEAN(1); r_result = graph; UNPROTECT(1); @@ -112,9 +115,9 @@ SEXP R_igraph_copy(SEXP from) { } /*-------------------------------------------/ -/ igraph_delete_vertices_idx / +/ igraph_delete_vertices_map / /-------------------------------------------*/ -SEXP R_igraph_delete_vertices_idx(SEXP graph, SEXP vertices) { +SEXP R_igraph_delete_vertices_map(SEXP graph, SEXP vertices) { /* Declarations */ igraph_t c_graph; igraph_vs_t c_vertices; @@ -138,7 +141,7 @@ SEXP R_igraph_delete_vertices_idx(SEXP graph, SEXP vertices) { } IGRAPH_FINALLY(igraph_vector_int_destroy, &c_invidx); /* Call igraph */ - IGRAPH_R_CHECK(igraph_delete_vertices_idx(&c_graph, c_vertices, &c_idx, &c_invidx)); + IGRAPH_R_CHECK(igraph_delete_vertices_map(&c_graph, c_vertices, &c_idx, &c_invidx)); /* Convert output */ PROTECT(r_result=NEW_LIST(3)); @@ -2305,13 +2308,14 @@ SEXP R_igraph_distances_bellman_ford(SEXP graph, SEXP from, SEXP to, SEXP weight /*-------------------------------------------/ / igraph_distances_johnson / /-------------------------------------------*/ -SEXP R_igraph_distances_johnson(SEXP graph, SEXP from, SEXP to, SEXP weights) { +SEXP R_igraph_distances_johnson(SEXP graph, SEXP from, SEXP to, SEXP weights, SEXP mode) { /* Declarations */ igraph_t c_graph; igraph_matrix_t c_res; igraph_vs_t c_from; igraph_vs_t c_to; igraph_vector_t c_weights; + igraph_neimode_t c_mode; SEXP res; SEXP r_result; @@ -2326,8 +2330,9 @@ SEXP R_igraph_distances_johnson(SEXP graph, SEXP from, SEXP to, SEXP weights) { igraph_vector_int_t c_to_data; R_SEXP_to_igraph_vs(to, &c_graph, &c_to, &c_to_data); if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } + c_mode = (igraph_neimode_t) Rf_asInteger(mode); /* Call igraph */ - IGRAPH_R_CHECK(igraph_distances_johnson(&c_graph, &c_res, c_from, c_to, (Rf_isNull(weights) ? 0 : &c_weights))); + IGRAPH_R_CHECK(igraph_distances_johnson(&c_graph, &c_res, c_from, c_to, (Rf_isNull(weights) ? 0 : &c_weights), c_mode)); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); @@ -5799,7 +5804,7 @@ SEXP R_igraph_bipartite_game_gnp(SEXP n1, SEXP n2, SEXP p, SEXP directed, SEXP m /*-------------------------------------------/ / igraph_bipartite_game_gnm / /-------------------------------------------*/ -SEXP R_igraph_bipartite_game_gnm(SEXP n1, SEXP n2, SEXP m, SEXP directed, SEXP mode) { +SEXP R_igraph_bipartite_game_gnm(SEXP n1, SEXP n2, SEXP m, SEXP directed, SEXP mode, SEXP multiple) { /* Declarations */ igraph_t c_graph; igraph_vector_bool_t c_types; @@ -5808,6 +5813,7 @@ SEXP R_igraph_bipartite_game_gnm(SEXP n1, SEXP n2, SEXP m, SEXP directed, SEXP m igraph_integer_t c_m; igraph_bool_t c_directed; igraph_neimode_t c_mode; + igraph_bool_t c_multiple; SEXP graph; SEXP types; @@ -5826,8 +5832,10 @@ SEXP R_igraph_bipartite_game_gnm(SEXP n1, SEXP n2, SEXP m, SEXP directed, SEXP m IGRAPH_R_CHECK_BOOL(directed); c_directed = LOGICAL(directed)[0]; c_mode = (igraph_neimode_t) Rf_asInteger(mode); + IGRAPH_R_CHECK_BOOL(multiple); + c_multiple = LOGICAL(multiple)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_bipartite_game_gnm(&c_graph, &c_types, c_n1, c_n2, c_m, c_directed, c_mode)); + IGRAPH_R_CHECK(igraph_bipartite_game_gnm(&c_graph, &c_types, c_n1, c_n2, c_m, c_directed, c_mode, c_multiple)); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -7051,11 +7059,12 @@ SEXP R_igraph_layout_umap_compute_weights(SEXP graph, SEXP distances, SEXP weigh /*-------------------------------------------/ / igraph_similarity_dice / /-------------------------------------------*/ -SEXP R_igraph_similarity_dice(SEXP graph, SEXP vids, SEXP mode, SEXP loops) { +SEXP R_igraph_similarity_dice(SEXP graph, SEXP vit_from, SEXP vit_to, SEXP mode, SEXP loops) { /* Declarations */ igraph_t c_graph; igraph_matrix_t c_res; - igraph_vs_t c_vids; + igraph_vs_t c_vit_from; + igraph_vs_t c_vit_to; igraph_neimode_t c_mode; igraph_bool_t c_loops; SEXP res; @@ -7067,20 +7076,24 @@ SEXP R_igraph_similarity_dice(SEXP graph, SEXP vids, SEXP mode, SEXP loops) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); - igraph_vector_int_t c_vids_data; - R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); + igraph_vector_int_t c_vit_from_data; + R_SEXP_to_igraph_vs(vit_from, &c_graph, &c_vit_from, &c_vit_from_data); + igraph_vector_int_t c_vit_to_data; + R_SEXP_to_igraph_vs(vit_to, &c_graph, &c_vit_to, &c_vit_to_data); c_mode = (igraph_neimode_t) Rf_asInteger(mode); IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_similarity_dice(&c_graph, &c_res, c_vids, c_mode, c_loops)); + IGRAPH_R_CHECK(igraph_similarity_dice(&c_graph, &c_res, c_vit_from, c_vit_to, c_mode, c_loops)); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); igraph_matrix_destroy(&c_res); IGRAPH_FINALLY_CLEAN(1); - igraph_vector_int_destroy(&c_vids_data); - igraph_vs_destroy(&c_vids); + igraph_vector_int_destroy(&c_vit_from_data); + igraph_vs_destroy(&c_vit_from); + igraph_vector_int_destroy(&c_vit_to_data); + igraph_vs_destroy(&c_vit_to); r_result = res; UNPROTECT(1); @@ -7204,11 +7217,12 @@ SEXP R_igraph_similarity_inverse_log_weighted(SEXP graph, SEXP vids, SEXP mode) /*-------------------------------------------/ / igraph_similarity_jaccard / /-------------------------------------------*/ -SEXP R_igraph_similarity_jaccard(SEXP graph, SEXP vids, SEXP mode, SEXP loops) { +SEXP R_igraph_similarity_jaccard(SEXP graph, SEXP vit_from, SEXP vit_to, SEXP mode, SEXP loops) { /* Declarations */ igraph_t c_graph; igraph_matrix_t c_res; - igraph_vs_t c_vids; + igraph_vs_t c_vit_from; + igraph_vs_t c_vit_to; igraph_neimode_t c_mode; igraph_bool_t c_loops; SEXP res; @@ -7220,20 +7234,24 @@ SEXP R_igraph_similarity_jaccard(SEXP graph, SEXP vids, SEXP mode, SEXP loops) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_matrix_destroy, &c_res); - igraph_vector_int_t c_vids_data; - R_SEXP_to_igraph_vs(vids, &c_graph, &c_vids, &c_vids_data); + igraph_vector_int_t c_vit_from_data; + R_SEXP_to_igraph_vs(vit_from, &c_graph, &c_vit_from, &c_vit_from_data); + igraph_vector_int_t c_vit_to_data; + R_SEXP_to_igraph_vs(vit_to, &c_graph, &c_vit_to, &c_vit_to_data); c_mode = (igraph_neimode_t) Rf_asInteger(mode); IGRAPH_R_CHECK_BOOL(loops); c_loops = LOGICAL(loops)[0]; /* Call igraph */ - IGRAPH_R_CHECK(igraph_similarity_jaccard(&c_graph, &c_res, c_vids, c_mode, c_loops)); + IGRAPH_R_CHECK(igraph_similarity_jaccard(&c_graph, &c_res, c_vit_from, c_vit_to, c_mode, c_loops)); /* Convert output */ PROTECT(res=R_igraph_matrix_to_SEXP(&c_res)); igraph_matrix_destroy(&c_res); IGRAPH_FINALLY_CLEAN(1); - igraph_vector_int_destroy(&c_vids_data); - igraph_vs_destroy(&c_vids); + igraph_vector_int_destroy(&c_vit_from_data); + igraph_vs_destroy(&c_vit_from); + igraph_vector_int_destroy(&c_vit_to_data); + igraph_vs_destroy(&c_vit_to); r_result = res; UNPROTECT(1); @@ -9465,6 +9483,77 @@ SEXP R_igraph_isomorphic(SEXP graph1, SEXP graph2) { return(r_result); } +/*-------------------------------------------/ +/ igraph_automorphism_group / +/-------------------------------------------*/ +SEXP R_igraph_automorphism_group(SEXP graph, SEXP colors) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_int_t c_colors; + igraph_vector_int_list_t c_generators; + SEXP generators; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(colors)) { + R_SEXP_to_vector_int_copy(colors, &c_colors); + } else { + IGRAPH_R_CHECK(igraph_vector_int_init(&c_colors, 0)); + } + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_colors); + if (0 != igraph_vector_int_list_init(&c_generators, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_generators); + /* Call igraph */ + IGRAPH_R_CHECK(igraph_automorphism_group(&c_graph, (Rf_isNull(colors) ? 0 : (Rf_isNull(colors) ? 0 : &c_colors)), &c_generators)); + + /* Convert output */ + igraph_vector_int_destroy(&c_colors); + IGRAPH_FINALLY_CLEAN(1); + PROTECT(generators=R_igraph_vector_int_list_to_SEXPp1(&c_generators)); + igraph_vector_int_list_destroy(&c_generators); + IGRAPH_FINALLY_CLEAN(1); + r_result = generators; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_count_automorphisms / +/-------------------------------------------*/ +SEXP R_igraph_count_automorphisms(SEXP graph, SEXP colors) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_int_t c_colors; + igraph_real_t c_result; + SEXP result; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(colors)) { + R_SEXP_to_vector_int_copy(colors, &c_colors); + } else { + IGRAPH_R_CHECK(igraph_vector_int_init(&c_colors, 0)); + } + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_colors); + /* Call igraph */ + IGRAPH_R_CHECK(igraph_count_automorphisms(&c_graph, (Rf_isNull(colors) ? 0 : (Rf_isNull(colors) ? 0 : &c_colors)), &c_result)); + + /* Convert output */ + igraph_vector_int_destroy(&c_colors); + IGRAPH_FINALLY_CLEAN(1); + PROTECT(result=NEW_NUMERIC(1)); + REAL(result)[0]=c_result; + r_result = result; + + UNPROTECT(1); + return(r_result); +} + /*-------------------------------------------/ / igraph_isoclass_subgraph / /-------------------------------------------*/ @@ -10013,7 +10102,45 @@ SEXP R_igraph_get_subisomorphisms_vf2(SEXP graph1, SEXP graph2, SEXP vertex_colo /*-------------------------------------------/ / igraph_canonical_permutation / /-------------------------------------------*/ -SEXP R_igraph_canonical_permutation(SEXP graph, SEXP colors, SEXP sh) { +SEXP R_igraph_canonical_permutation(SEXP graph, SEXP colors) { + /* Declarations */ + igraph_t c_graph; + igraph_vector_int_t c_colors; + igraph_vector_int_t c_labeling; + SEXP labeling; + + SEXP r_result; + /* Convert input */ + R_SEXP_to_igraph(graph, &c_graph); + if (!Rf_isNull(colors)) { + R_SEXP_to_vector_int_copy(colors, &c_colors); + } else { + IGRAPH_R_CHECK(igraph_vector_int_init(&c_colors, 0)); + } + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_colors); + if (0 != igraph_vector_int_init(&c_labeling, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY(igraph_vector_int_destroy, &c_labeling); + /* Call igraph */ + IGRAPH_R_CHECK(igraph_canonical_permutation(&c_graph, (Rf_isNull(colors) ? 0 : (Rf_isNull(colors) ? 0 : &c_colors)), &c_labeling)); + + /* Convert output */ + igraph_vector_int_destroy(&c_colors); + IGRAPH_FINALLY_CLEAN(1); + PROTECT(labeling=R_igraph_vector_int_to_SEXPp1(&c_labeling)); + igraph_vector_int_destroy(&c_labeling); + IGRAPH_FINALLY_CLEAN(1); + r_result = labeling; + + UNPROTECT(1); + return(r_result); +} + +/*-------------------------------------------/ +/ igraph_canonical_permutation_bliss / +/-------------------------------------------*/ +SEXP R_igraph_canonical_permutation_bliss(SEXP graph, SEXP colors, SEXP sh) { /* Declarations */ igraph_t c_graph; igraph_vector_int_t c_colors; @@ -10038,7 +10165,7 @@ SEXP R_igraph_canonical_permutation(SEXP graph, SEXP colors, SEXP sh) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_labeling); c_sh = (igraph_bliss_sh_t) Rf_asInteger(sh); /* Call igraph */ - IGRAPH_R_CHECK(igraph_canonical_permutation(&c_graph, (Rf_isNull(colors) ? 0 : (Rf_isNull(colors) ? 0 : &c_colors)), &c_labeling, c_sh, &c_info)); + IGRAPH_R_CHECK(igraph_canonical_permutation_bliss(&c_graph, (Rf_isNull(colors) ? 0 : (Rf_isNull(colors) ? 0 : &c_colors)), &c_labeling, c_sh, &c_info)); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); @@ -10178,9 +10305,9 @@ SEXP R_igraph_isomorphic_bliss(SEXP graph1, SEXP graph2, SEXP colors1, SEXP colo } /*-------------------------------------------/ -/ igraph_count_automorphisms / +/ igraph_count_automorphisms_bliss / /-------------------------------------------*/ -SEXP R_igraph_count_automorphisms(SEXP graph, SEXP colors, SEXP sh) { +SEXP R_igraph_count_automorphisms_bliss(SEXP graph, SEXP colors, SEXP sh) { /* Declarations */ igraph_t c_graph; igraph_vector_int_t c_colors; @@ -10199,7 +10326,7 @@ SEXP R_igraph_count_automorphisms(SEXP graph, SEXP colors, SEXP sh) { IGRAPH_FINALLY(igraph_vector_int_destroy, &c_colors); c_sh = (igraph_bliss_sh_t) Rf_asInteger(sh); /* Call igraph */ - IGRAPH_R_CHECK(igraph_count_automorphisms(&c_graph, (Rf_isNull(colors) ? 0 : (Rf_isNull(colors) ? 0 : &c_colors)), c_sh, &c_info)); + IGRAPH_R_CHECK(igraph_count_automorphisms_bliss(&c_graph, (Rf_isNull(colors) ? 0 : (Rf_isNull(colors) ? 0 : &c_colors)), c_sh, &c_info)); /* Convert output */ igraph_vector_int_destroy(&c_colors); @@ -10213,9 +10340,9 @@ SEXP R_igraph_count_automorphisms(SEXP graph, SEXP colors, SEXP sh) { } /*-------------------------------------------/ -/ igraph_automorphism_group / +/ igraph_automorphism_group_bliss / /-------------------------------------------*/ -SEXP R_igraph_automorphism_group(SEXP graph, SEXP colors, SEXP sh) { +SEXP R_igraph_automorphism_group_bliss(SEXP graph, SEXP colors, SEXP sh) { /* Declarations */ igraph_t c_graph; igraph_vector_int_t c_colors; @@ -10240,7 +10367,7 @@ SEXP R_igraph_automorphism_group(SEXP graph, SEXP colors, SEXP sh) { IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_generators); c_sh = (igraph_bliss_sh_t) Rf_asInteger(sh); /* Call igraph */ - IGRAPH_R_CHECK(igraph_automorphism_group(&c_graph, (Rf_isNull(colors) ? 0 : (Rf_isNull(colors) ? 0 : &c_colors)), &c_generators, c_sh, &c_info)); + IGRAPH_R_CHECK(igraph_automorphism_group_bliss(&c_graph, (Rf_isNull(colors) ? 0 : (Rf_isNull(colors) ? 0 : &c_colors)), &c_generators, c_sh, &c_info)); /* Convert output */ PROTECT(r_result=NEW_LIST(2)); diff --git a/src/rinterface.h b/src/rinterface.h index 2ef7b02705e..c4b7d6d14af 100644 --- a/src/rinterface.h +++ b/src/rinterface.h @@ -37,7 +37,7 @@ #include "uuid/uuid.h" -#define IGRAPH_I_DESTROY IGRAPH_I_ATTRIBUTE_DESTROY +#define IGRAPH_I_DESTROY igraph_i_attribute_destroy SEXP R_igraph_add_env(SEXP graph); diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 42864c74259..2ac8eeb4ace 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -315,7 +315,7 @@ void R_igraph_attribute_clean_preserve_list(void) { } } -igraph_error_t R_igraph_attribute_init(igraph_t *graph, igraph_vector_ptr_t *attr) { +igraph_error_t R_igraph_attribute_init(igraph_t *graph, const igraph_attribute_record_list_t *attr) { SEXP result, names, gal; int px = 0; @@ -341,12 +341,12 @@ igraph_error_t R_igraph_attribute_init(igraph_t *graph, igraph_vector_ptr_t *att graph->attr=result; /* Add graph attributes */ - igraph_integer_t attrno= attr==NULL ? 0 : igraph_vector_ptr_size(attr); + igraph_integer_t attrno= attr==NULL ? 0 : igraph_attribute_record_list_size(attr); SET_VECTOR_ELT(result, 1, NEW_LIST(attrno)); gal=VECTOR_ELT(result, 1); PROTECT(names=NEW_CHARACTER(attrno)); px++; for (igraph_integer_t i=0; itype) { case IGRAPH_ATTRIBUTE_NUMERIC: - vec=(igraph_vector_t*) rec->value; + vec=(igraph_vector_t*) rec->value.as_vector; if (igraph_vector_size(vec) > 0) { SET_VECTOR_ELT(gal, i, NEW_NUMERIC(1)); REAL(VECTOR_ELT(gal, i))[0]=VECTOR(*vec)[0]; } break; case IGRAPH_ATTRIBUTE_BOOLEAN: - log=(igraph_vector_bool_t*) rec->value; + log=(igraph_vector_bool_t*) rec->value.as_vector_bool; if (igraph_vector_bool_size(log) > 0) { SET_VECTOR_ELT(gal, i, NEW_LOGICAL(1)); LOGICAL(VECTOR_ELT(gal, i))[0]=VECTOR(*log)[0]; } break; case IGRAPH_ATTRIBUTE_STRING: - strvec=(igraph_strvector_t*) rec->value; + strvec=(igraph_strvector_t*) rec->value.as_strvector; if (igraph_strvector_size(strvec) > 0) { SET_VECTOR_ELT(gal, i, NEW_CHARACTER(1)); SET_STRING_ELT(VECTOR_ELT(gal,i), 0, Rf_mkChar(igraph_strvector_get(strvec, 0))); @@ -424,22 +424,22 @@ igraph_error_t R_igraph_attribute_copy(igraph_t *to, const igraph_t *from, return 0; } -SEXP R_igraph_attribute_add_vertices_append1(igraph_vector_ptr_t *nattr, +SEXP R_igraph_attribute_add_vertices_append1(const igraph_attribute_record_list_t *nattr, int j, int nv) { SEXP app = R_NilValue; - igraph_attribute_record_t *tmprec=VECTOR(*nattr)[j-1]; + igraph_attribute_record_t *tmprec=igraph_attribute_record_list_get_ptr(nattr, j-1); igraph_integer_t len = 0; switch (tmprec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: - len = igraph_vector_size(tmprec->value); + len = igraph_vector_size(tmprec->value.as_vector); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - len = igraph_vector_bool_size(tmprec->value); + len = igraph_vector_bool_size(tmprec->value.as_vector_bool); break; case IGRAPH_ATTRIBUTE_STRING: - len = igraph_strvector_size(tmprec->value); + len = igraph_strvector_size(tmprec->value.as_strvector); break; case IGRAPH_ATTRIBUTE_OBJECT: igraph_error("R objects not implemented yet", __FILE__, __LINE__, @@ -462,13 +462,13 @@ SEXP R_igraph_attribute_add_vertices_append1(igraph_vector_ptr_t *nattr, switch (tmprec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: PROTECT(app=NEW_NUMERIC(nv)); - igraph_vector_copy_to(tmprec->value, REAL(app)); + igraph_vector_copy_to(tmprec->value.as_vector, REAL(app)); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - PROTECT(app=R_igraph_vector_bool_to_SEXP(tmprec->value)); + PROTECT(app=R_igraph_vector_bool_to_SEXP(tmprec->value.as_vector_bool)); break; default: /* IGRAPH_ATTRIBUTE_STRING */ - PROTECT(app=R_igraph_strvector_to_SEXP(tmprec->value)); + PROTECT(app=R_igraph_strvector_to_SEXP(tmprec->value.as_strvector)); break; } @@ -477,7 +477,7 @@ SEXP R_igraph_attribute_add_vertices_append1(igraph_vector_ptr_t *nattr, } void R_igraph_attribute_add_vertices_append(SEXP val, igraph_integer_t nv, - igraph_vector_ptr_t *nattr) { + const igraph_attribute_record_list_t *nattr) { SEXP names; igraph_integer_t valno, nattrno; SEXP rep = R_NilValue; @@ -488,7 +488,7 @@ void R_igraph_attribute_add_vertices_append(SEXP val, igraph_integer_t nv, if (nattr==NULL) { nattrno=0; } else { - nattrno=igraph_vector_ptr_size(nattr); + nattrno=igraph_attribute_record_list_size(nattr); } for (igraph_integer_t i=0; iname); } if (l) { @@ -531,7 +531,7 @@ SEXP R_igraph_attribute_add_vertices_dup(SEXP attr) { } igraph_error_t R_igraph_attribute_add_vertices(igraph_t *graph, igraph_integer_t nv, - igraph_vector_ptr_t *nattr) { + const igraph_attribute_record_list_t *nattr) { SEXP attr=graph->attr; SEXP val, rep=0, names, newnames; igraph_vector_int_t news; @@ -547,7 +547,7 @@ igraph_error_t R_igraph_attribute_add_vertices(igraph_t *graph, igraph_integer_t if (nattr==NULL) { nattrno=0; } else { - nattrno=igraph_vector_ptr_size(nattr); + nattrno=igraph_attribute_record_list_size(nattr); } origlen=igraph_vcount(graph)-nv; @@ -556,7 +556,7 @@ igraph_error_t R_igraph_attribute_add_vertices(igraph_t *graph, igraph_integer_t if (igraph_vector_int_init(&news, 0)) Rf_error("Out of memory"); IGRAPH_FINALLY(igraph_vector_int_destroy, &news); for (igraph_integer_t i=0; iname; igraph_bool_t l=0; for (igraph_integer_t j=0; !l && jname)); } @@ -759,22 +759,22 @@ SEXP R_igraph_attribute_add_edges_dup(SEXP attr) { return newattr; } -SEXP R_igraph_attribute_add_edges_append1(igraph_vector_ptr_t *nattr, igraph_integer_t j, +SEXP R_igraph_attribute_add_edges_append1(const igraph_attribute_record_list_t *nattr, igraph_integer_t j, igraph_integer_t ne) { SEXP app = R_NilValue; - igraph_attribute_record_t *tmprec=VECTOR(*nattr)[j-1]; + igraph_attribute_record_t *tmprec=igraph_attribute_record_list_get_ptr(nattr, j-1); igraph_integer_t len = 0; switch(tmprec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: - len = igraph_vector_size(tmprec->value); + len = igraph_vector_size(tmprec->value.as_vector); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - len = igraph_vector_bool_size(tmprec->value); + len = igraph_vector_bool_size(tmprec->value.as_vector_bool); break; case IGRAPH_ATTRIBUTE_STRING: - len = igraph_strvector_size(tmprec->value); + len = igraph_strvector_size(tmprec->value.as_strvector); break; case IGRAPH_ATTRIBUTE_OBJECT: igraph_error("R objects not implemented yet", __FILE__, __LINE__, @@ -797,13 +797,13 @@ SEXP R_igraph_attribute_add_edges_append1(igraph_vector_ptr_t *nattr, igraph_int switch (tmprec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: PROTECT(app=NEW_NUMERIC(ne)); - igraph_vector_copy_to(tmprec->value, REAL(app)); + igraph_vector_copy_to(tmprec->value.as_vector, REAL(app)); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - PROTECT(app=R_igraph_vector_bool_to_SEXP(tmprec->value)); + PROTECT(app=R_igraph_vector_bool_to_SEXP(tmprec->value.as_vector_bool)); break; default: /* IGRAPH_ATTRIBUTE_STRING */ - PROTECT(app=R_igraph_strvector_to_SEXP(tmprec->value)); + PROTECT(app=R_igraph_strvector_to_SEXP(tmprec->value.as_strvector)); break; } @@ -813,7 +813,7 @@ SEXP R_igraph_attribute_add_edges_append1(igraph_vector_ptr_t *nattr, igraph_int void R_igraph_attribute_add_edges_append(SEXP eal, const igraph_vector_int_t *edges, - igraph_vector_ptr_t *nattr) { + const igraph_attribute_record_list_t *nattr) { SEXP names; igraph_integer_t ealno; igraph_integer_t ne=igraph_vector_int_size(edges)/2, nattrno; @@ -825,7 +825,7 @@ void R_igraph_attribute_add_edges_append(SEXP eal, if (nattr==NULL) { nattrno=0; } else { - nattrno=igraph_vector_ptr_size(nattr); + nattrno=igraph_attribute_record_list_size(nattr); } for (igraph_integer_t i=0; iname); } if (l) { @@ -862,7 +862,7 @@ void R_igraph_attribute_add_edges_append(SEXP eal, } igraph_error_t R_igraph_attribute_add_edges(igraph_t *graph, const igraph_vector_int_t *edges, - igraph_vector_ptr_t *nattr) { + const igraph_attribute_record_list_t *nattr) { SEXP attr=graph->attr; SEXP eal, names, newnames; igraph_vector_int_t news; @@ -882,14 +882,14 @@ igraph_error_t R_igraph_attribute_add_edges(igraph_t *graph, const igraph_vector if (nattr==NULL) { nattrno=0; } else { - nattrno=igraph_vector_ptr_size(nattr); + nattrno=igraph_attribute_record_list_size(nattr); } origlen=igraph_ecount(graph)-ne; /* First add the new attributes, if any */ newattrs=0; for (igraph_integer_t i=0; iname; igraph_bool_t l=0; for (igraph_integer_t j=0; !l && jname)); } @@ -1836,7 +1836,7 @@ igraph_error_t R_igraph_attribute_combine_vertices(const igraph_t *graph, /* Create the TODO list first */ PROTECT(names=GET_NAMES(val)); px++; - TODO=igraph_Calloc(valno, igraph_integer_t); + TODO=IGRAPH_CALLOC(valno, igraph_integer_t); if (!TODO) { UNPROTECT(px); IGRAPH_ERROR("Cannot combine edge attributes", @@ -2010,7 +2010,7 @@ igraph_error_t R_igraph_attribute_combine_edges(const igraph_t *graph, IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, TODO); - funcs=igraph_Calloc(ealno, igraph_function_pointer_t); + funcs=IGRAPH_CALLOC(ealno, igraph_function_pointer_t); if (!funcs) { UNPROTECT(px); IGRAPH_ERROR("Cannot combine edge attributes", @@ -2283,7 +2283,7 @@ void checkInterruptFn(void *dummy) { R_CheckUserInterrupt(); } -igraph_error_t R_igraph_interrupt_handler(void *data) { +igraph_bool_t R_igraph_interrupt_handler() { /* We need to call R_CheckUserInterrupt() regularly to enable interruptions. * However, if an interruption is pending, R_CheckUserInterrupt() will * longjmp back to the top level so we cannot clean up ourselves by calling @@ -2299,9 +2299,9 @@ igraph_error_t R_igraph_interrupt_handler(void *data) { */ if (R_ToplevelExec(checkInterruptFn, NULL) == FALSE) { IGRAPH_FINALLY_FREE(); - return IGRAPH_INTERRUPTED; + return 1; } - return IGRAPH_SUCCESS; + return 0; } igraph_error_t R_igraph_progress_handler(const char *message, double percent, @@ -3325,7 +3325,7 @@ void R_igraph_SEXP_to_matrixlist(SEXP matrixlist, igraph_matrix_list_t *list) { igraph_error_t R_igraph_SEXP_to_strvector(SEXP rval, igraph_strvector_t *sv) { igraph_integer_t length = Rf_xlength(rval); - sv->stor_begin=(char**) R_alloc((size_t) length, sizeof(char*)); + sv->stor_begin=(const char**) R_alloc((size_t) length, sizeof(char*)); sv->stor_end=sv->stor_begin+length; sv->end=sv->stor_end; for (igraph_integer_t i=0; iAttributes are numbers, boolean values or strings associated with - * the vertices or edges of a graph, or with the graph itself. E.g. you may - * label vertices with symbolic names or attach numeric weights to the edges - * of a graph. In addition to these three basic types, a custom object - * type is supported as well. - * - * igraph attributes are designed to be flexible and extensible. - * In igraph attributes are implemented via an interface abstraction: - * any type implementing the functions in the interface, can be used - * for storing vertex, edge and graph attributes. This means that - * different attribute implementations can be used together with - * igraph. This is reasonable: if igraph is used from Python attributes can be - * of any Python type, from R all R types are allowed. There is also an - * experimental attribute implementation to be used when programming - * in C, but by default it is currently turned off. - * - * First we briefly look over how attribute handlers can be - * implemented. This is not something a user does every day. It is - * rather typically the job of the high level interface writers. (But - * it is possible to write an interface without implementing - * attributes.) Then we show the experimental C attribute handler. - */ - -/** - * \section about_attribute_table - * It is possible to attach an attribute handling - * interface to \a igraph. This is simply a table of functions, of - * type \ref igraph_attribute_table_t. These functions are invoked to - * notify the attribute handling code about the structural changes in - * a graph. See the documentation of this type for details. - * - * By default there is no attribute interface attached to \a igraph. - * To attach one, call \ref igraph_set_attribute_table with your new - * table. This is normally done on program startup, and is kept untouched - * for the program's lifetime. It must be done before any graph object - * is created, as graphs created with a given attribute handler - * cannot be manipulated while a different attribute handler is - * active. - */ - -/** - * \section about_attribute_combination - * - * Several graph operations may collapse multiple vertices or edges into - * a single one. Attribute combination lists are used to indicate to the attribute - * handler how to combine the attributes of the original vertices or edges and - * how to derive the final attribute value that is to be assigned to the collapsed - * vertex or edge. For example, \ref igraph_simplify() removes loops and combines - * multiple edges into a single one; in case of a graph with an edge attribute - * named \c weight the attribute combination list can tell the attribute handler - * whether the weight of a collapsed edge should be the sum, the mean or some other - * function of the weights of the original edges that were collapsed into one. - * - * One attribute combination list may contain several attribute combination - * records, one for each vertex or edge attribute that is to be handled during the - * operation. - */ - /** * \typedef igraph_attribute_type_t - * The possible types of the attributes. - * - * Note that this is only the - * type communicated by the attribute interface towards igraph - * functions. E.g. in the R attribute handler, it is safe to say - * that all complex R object attributes are strings, as long as this - * interface is able to serialize them into strings. See also \ref - * igraph_attribute_table_t. + * \brief The possible types of the attributes. + * + * Values of this enum are used by the attribute interface to communicate the + * type of an attribute to igraph's C core. When igraph is integrated in a + * high-level language, the attribute type reported by the interface may not + * necessarily have to match the exact data type in the high-level language as + * long as the attribute interface can provide a conversion from the native + * high-level attribute value to one of the data types listed here. When the + * high-level data type is complex and has no suitable conversion to one of the + * atomic igraph attribute types (numeric, string or Boolean), the attribute + * interface should report the attribute as having an "object" type, which is + * ignored by the C core. See also \ref igraph_attribute_table_t. + * * \enumval IGRAPH_ATTRIBUTE_UNSPECIFIED Currently used internally * as a "null value" or "placeholder value" in some algorithms. * Attribute records with this type must not be passed to igraph * functions. * \enumval IGRAPH_ATTRIBUTE_NUMERIC Numeric attribute. * \enumval IGRAPH_ATTRIBUTE_BOOLEAN Logical values, true or false. - * \enumval IGRAPH_ATTRIBUTE_STRING Attribute that can be converted to - * a string. + * \enumval IGRAPH_ATTRIBUTE_STRING String attribute. * \enumval IGRAPH_ATTRIBUTE_OBJECT Custom attribute type, to be * used for special data types by client applications. The R and * Python interfaces use this for attributes that hold R or Python * objects. Usually ignored by igraph functions. */ -typedef enum { IGRAPH_ATTRIBUTE_UNSPECIFIED = 0, - IGRAPH_ATTRIBUTE_DEFAULT IGRAPH_DEPRECATED_ENUMVAL = IGRAPH_ATTRIBUTE_UNSPECIFIED, - IGRAPH_ATTRIBUTE_NUMERIC = 1, - IGRAPH_ATTRIBUTE_BOOLEAN = 2, - IGRAPH_ATTRIBUTE_STRING = 3, - IGRAPH_ATTRIBUTE_OBJECT = 127 - } igraph_attribute_type_t; +typedef enum { + IGRAPH_ATTRIBUTE_UNSPECIFIED = 0, + IGRAPH_ATTRIBUTE_DEFAULT IGRAPH_DEPRECATED_ENUMVAL = IGRAPH_ATTRIBUTE_UNSPECIFIED, + IGRAPH_ATTRIBUTE_NUMERIC = 1, + IGRAPH_ATTRIBUTE_BOOLEAN = 2, + IGRAPH_ATTRIBUTE_STRING = 3, + IGRAPH_ATTRIBUTE_OBJECT = 127 +} igraph_attribute_type_t; +/** + * \typedef igraph_attribute_elemtype_t + * \brief Types of objects to which attributes can be attached. + * + * \enumval IGRAPH_ATTRIBUTE_GRAPH Denotes that an attribute belongs to the + * entire graph. + * \enumval IGRAPH_ATTRIBUTE_VERTEX Denotes that an attribute belongs to the + * vertices of a graph. + * \enumval IGRAPH_ATTRIBUTE_EDGE Denotes that an attribute belongs to the + * edges of a graph. + */ +typedef enum { + IGRAPH_ATTRIBUTE_GRAPH = 0, + IGRAPH_ATTRIBUTE_VERTEX, + IGRAPH_ATTRIBUTE_EDGE +} igraph_attribute_elemtype_t; + +/* -------------------------------------------------- */ +/* Attribute records */ +/* -------------------------------------------------- */ + +/** + * \typedef igraph_attribute_record_t + * \brief An attribute record holding the name, type and values of an attribute. + * + * This composite data type is used in the attribute interface to specify a + * name-type-value triplet where the name is the name of a graph, vertex or + * edge attribute, the type is the corresponding igraph type of the attribute + * and the value is a \em vector of attribute values. Note that for graph + * attributes we use a vector of length 1. The type of the vector depends on + * the attribute type: it is \ref igraph_vector_t for numeric attributes, + * \c igraph_strvector_t for string attributes and \c igraph_vector_bool_t + * for Boolean attributes. + * + * + * The record also stores default values for the attribute. The default values + * are used when the value vector of the record is resized with + * \ref igraph_attribute_record_resize(). It is important that the record + * stores \em one default value only, corresponding to the type of the + * attribute record. The default value is \em cleared when the type of the + * record is changed. + */ typedef struct igraph_attribute_record_t { - const char *name; + char *name; igraph_attribute_type_t type; - const void *value; + union { + void *as_raw; + igraph_vector_t *as_vector; + igraph_strvector_t *as_strvector; + igraph_vector_bool_t *as_vector_bool; + } value; + union { + igraph_real_t numeric; + igraph_bool_t boolean; + char *string; + } default_value; } igraph_attribute_record_t; -typedef enum { IGRAPH_ATTRIBUTE_GRAPH = 0, - IGRAPH_ATTRIBUTE_VERTEX, - IGRAPH_ATTRIBUTE_EDGE - } igraph_attribute_elemtype_t; +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_init( + igraph_attribute_record_t *attr, const char* name, igraph_attribute_type_t type +); +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_init_copy( + igraph_attribute_record_t *to, const igraph_attribute_record_t *from +); +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_check_type( + const igraph_attribute_record_t *attr, igraph_attribute_type_t type +); +IGRAPH_EXPORT igraph_integer_t igraph_attribute_record_size( + const igraph_attribute_record_t *attr +); +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_resize( + igraph_attribute_record_t *attr, igraph_integer_t new_size +); +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_set_name( + igraph_attribute_record_t *attr, const char* name +); +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_set_default_numeric( + igraph_attribute_record_t *attr, igraph_real_t value +); +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_set_default_boolean( + igraph_attribute_record_t *attr, igraph_bool_t value +); +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_set_default_string( + igraph_attribute_record_t *attr, const char* value +); +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_set_type( + igraph_attribute_record_t *attr, igraph_attribute_type_t type +); +IGRAPH_EXPORT void igraph_attribute_record_destroy(igraph_attribute_record_t *attr); + +/* -------------------------------------------------- */ +/* Attribute combinations */ +/* -------------------------------------------------- */ /** * \typedef igraph_attribute_combination_type_t @@ -207,6 +234,22 @@ IGRAPH_EXPORT igraph_error_t igraph_attribute_combination_query(const igraph_att igraph_attribute_combination_type_t *type, igraph_function_pointer_t *func); +/* -------------------------------------------------- */ +/* List of attribute records */ +/* -------------------------------------------------- */ + +#define ATTRIBUTE_RECORD_LIST +#define BASE_ATTRIBUTE_RECORD +#include "igraph_pmt.h" +#include "igraph_typed_list_pmt.h" +#include "igraph_pmt_off.h" +#undef BASE_ATTRIBUTE_RECORD +#undef ATTRIBUTE_RECORD_LIST + +/* -------------------------------------------------- */ +/* Attribute handler interface */ +/* -------------------------------------------------- */ + /** * \struct igraph_attribute_table_t * \brief Table of functions to perform operations on attributes. @@ -218,18 +261,23 @@ IGRAPH_EXPORT igraph_error_t igraph_attribute_combination_query(const igraph_att * created, right after it is created but before any vertices or * edges are added. It is supposed to set the \c attr member of the \c * igraph_t object, which is guaranteed to be set to a null pointer - * before this function is called. It is expected to return an error code. + * before this function is called. It is expected to set the \c attr member + * to a non-null value \em or return an error code. Leaving the \c attr + * member at a null value while returning success is invalid and will trigger + * an error in the C core of igraph itself. * \member destroy This function is called whenever the graph object * is destroyed, right before freeing the allocated memory. It is supposed * to do any cleanup operations that are need to dispose of the \c attr * member of the \c igraph_t object properly. The caller will set the * \c attr member to a null pointer after this function returns. - * \member copy This function is called when copying a graph with \ref - * igraph_copy, after the structure of the graph has been already - * copied. It is supposed to populate the \c attr member of the target - * \c igraph_t object. The \c attr member of the target is guaranteed to be - * set to a null pointer before this function is called. It is expected to - * return an error code. + * \member copy This function is called when the C core wants to populate the + * attributes of a graph from another graph. The struvture of the target + * graph is already initialized by the time this function is called, and the + * \c attr member of the graph is set to null pointer. The function is + * supposed to populate the \c attr member of the target \c igraph_t object + * to a non-null value \em or return an error code. Leaving the \c attr + * member at a null value while returning success is invalid and will trigger + * an error in the C core of igraph itself. * \member add_vertices Called when vertices are added to a * graph, before adding the vertices themselves. * The number of vertices to add is supplied as an @@ -311,11 +359,14 @@ IGRAPH_EXPORT igraph_error_t igraph_attribute_combination_query(const igraph_att */ typedef struct igraph_attribute_table_t { - igraph_error_t (*init)(igraph_t *graph, igraph_vector_ptr_t *attr); + igraph_error_t (*init)(igraph_t *graph, const igraph_attribute_record_list_t *attr); void (*destroy)(igraph_t *graph); igraph_error_t (*copy)(igraph_t *to, const igraph_t *from, igraph_bool_t ga, igraph_bool_t va, igraph_bool_t ea); - igraph_error_t (*add_vertices)(igraph_t *graph, igraph_integer_t nv, igraph_vector_ptr_t *attr); + igraph_error_t (*add_vertices)( + igraph_t *graph, igraph_integer_t nv, + const igraph_attribute_record_list_t *attr + ); igraph_error_t (*permute_vertices)(const igraph_t *graph, igraph_t *newgraph, const igraph_vector_int_t *idx); @@ -323,8 +374,10 @@ typedef struct igraph_attribute_table_t { igraph_t *newgraph, const igraph_vector_int_list_t *merges, const igraph_attribute_combination_t *comb); - igraph_error_t (*add_edges)(igraph_t *graph, const igraph_vector_int_t *edges, - igraph_vector_ptr_t *attr); + igraph_error_t (*add_edges)( + igraph_t *graph, const igraph_vector_int_t *edges, + const igraph_attribute_record_list_t *attr + ); igraph_error_t (*permute_edges)(const igraph_t *graph, igraph_t *newgraph, const igraph_vector_int_t *idx); igraph_error_t (*combine_edges)(const igraph_t *graph, diff --git a/src/vendor/cigraph/include/igraph_bipartite.h b/src/vendor/cigraph/include/igraph_bipartite.h index f32fe8aa7fb..4d6963fe10c 100644 --- a/src/vendor/cigraph/include/igraph_bipartite.h +++ b/src/vendor/cigraph/include/igraph_bipartite.h @@ -85,7 +85,7 @@ IGRAPH_EXPORT igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_v IGRAPH_EXPORT igraph_error_t igraph_bipartite_game_gnm(igraph_t *graph, igraph_vector_bool_t *types, igraph_integer_t n1, igraph_integer_t n2, igraph_integer_t m, igraph_bool_t directed, - igraph_neimode_t mode); + igraph_neimode_t mode, igraph_bool_t multiple); /* Deprecated functions: */ diff --git a/src/vendor/cigraph/include/igraph_cocitation.h b/src/vendor/cigraph/include/igraph_cocitation.h index 4dfd406ab94..0ee80267511 100644 --- a/src/vendor/cigraph/include/igraph_cocitation.h +++ b/src/vendor/cigraph/include/igraph_cocitation.h @@ -43,16 +43,16 @@ IGRAPH_EXPORT igraph_error_t igraph_bibcoupling(const igraph_t *graph, igraph_ma const igraph_vs_t vids); IGRAPH_EXPORT igraph_error_t igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t vids, igraph_neimode_t mode, - igraph_bool_t loops); + const igraph_vs_t vit_from, const igraph_vs_t vit_to, + igraph_neimode_t mode, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_similarity_jaccard_pairs(const igraph_t *graph, igraph_vector_t *res, const igraph_vector_int_t *pairs, igraph_neimode_t mode, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_similarity_jaccard_es(const igraph_t *graph, igraph_vector_t *res, const igraph_es_t es, igraph_neimode_t mode, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_similarity_dice(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t vids, igraph_neimode_t mode, - igraph_bool_t loops); + const igraph_vs_t vit_from, const igraph_vs_t vit_to, + igraph_neimode_t mode, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_similarity_dice_pairs(const igraph_t *graph, igraph_vector_t *res, const igraph_vector_int_t *pairs, igraph_neimode_t mode, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_similarity_dice_es(const igraph_t *graph, igraph_vector_t *res, diff --git a/src/vendor/cigraph/include/igraph_community.h b/src/vendor/cigraph/include/igraph_community.h index c38cef130b2..2c84049a722 100644 --- a/src/vendor/cigraph/include/igraph_community.h +++ b/src/vendor/cigraph/include/igraph_community.h @@ -79,8 +79,8 @@ IGRAPH_EXPORT igraph_error_t igraph_community_spinglass_single(const igraph_t *g igraph_vector_int_t *community, igraph_real_t *cohesion, igraph_real_t *adhesion, - igraph_integer_t *inner_links, - igraph_integer_t *outer_links, + igraph_real_t *inner_links, + igraph_real_t *outer_links, igraph_integer_t spins, igraph_spincomm_update_t update_rule, igraph_real_t gamma); diff --git a/src/vendor/cigraph/include/igraph_components.h b/src/vendor/cigraph/include/igraph_components.h index 30721b801eb..2f5b4152250 100644 --- a/src/vendor/cigraph/include/igraph_components.h +++ b/src/vendor/cigraph/include/igraph_components.h @@ -33,7 +33,6 @@ #include "igraph_types.h" #include "igraph_vector.h" #include "igraph_vector_list.h" -#include "igraph_vector_ptr.h" /* because of igraph_decompose_destroy() */ __BEGIN_DECLS @@ -64,10 +63,6 @@ IGRAPH_EXPORT igraph_error_t igraph_biconnected_components(const igraph_t *graph IGRAPH_EXPORT igraph_error_t igraph_is_biconnected(const igraph_t *graph, igraph_bool_t *result); IGRAPH_EXPORT igraph_error_t igraph_bridges(const igraph_t *graph, igraph_vector_int_t *bridges); -/* Deprecated in igraph 0.10 when we switched to igraph_graph_list_t. Will be - * removed in 0.11 */ -IGRAPH_EXPORT IGRAPH_DEPRECATED void igraph_decompose_destroy(igraph_vector_ptr_t *complist); - __END_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_error.h b/src/vendor/cigraph/include/igraph_error.h index 31060dca53c..b15a17369c4 100644 --- a/src/vendor/cigraph/include/igraph_error.h +++ b/src/vendor/cigraph/include/igraph_error.h @@ -252,11 +252,8 @@ __BEGIN_DECLS * number was specified as the number of vertices. * \enumval IGRAPH_EXISTS A graph/vertex/edge attribute is already * installed with the given name. - * \enumval IGRAPH_EINVEVECTOR Invalid vector of vertex IDs. A vertex ID - * is either negative or bigger than the number of vertices minus one. * \enumval IGRAPH_EINVVID Invalid vertex ID, negative or too big. - * \enumval IGRAPH_NONSQUARE A non-square matrix was received while a - * square matrix was expected. + * \enumval IGRAPH_EINVEID Invalid edge ID, negative or too big. * \enumval IGRAPH_EINVMODE Invalid mode parameter. * \enumval IGRAPH_EFILE A file operation failed. E.g. a file doesn't exist, * or the user has no rights to open it. @@ -287,7 +284,6 @@ __BEGIN_DECLS * \enumval IGRAPH_ARPACK_UNKNOWN Unknown ARPACK error. * \enumval IGRAPH_ENEGLOOP Negative loop detected while calculating shortest paths. * \enumval IGRAPH_EINTERNAL Internal error, likely a bug in igraph. - * \enumval IGRAPH_EDIVZERO Big integer division by zero. * \enumval IGRAPH_GLP_EBOUND GLPK error (GLP_EBOUND). * \enumval IGRAPH_GLP_EROOT GLPK error (GLP_EROOT). * \enumval IGRAPH_GLP_ENOPFS GLPK error (GLP_ENOPFS). @@ -296,14 +292,9 @@ __BEGIN_DECLS * \enumval IGRAPH_GLP_EMIPGAP GLPK error (GLP_EMIPGAP). * \enumval IGRAPH_GLP_ETMLIM GLPK error (GLP_ETMLIM). * \enumval IGRAPH_GLP_ESTOP GLPK error (GLP_ESTOP). - * \enumval IGRAPH_EATTRIBUTES Attribute handler error. The user is not - * expected to find this; it is signalled if some igraph function is - * not using the attribute handler interface properly. * \enumval IGRAPH_EATTRCOMBINE Unimplemented attribute combination * method for the given attribute type. * \enumval IGRAPH_ELAPACK A LAPACK call resulted in an error. - * \enumval IGRAPH_EDRL Internal error in the DrL layout generator; not used - * any more (replaced by IGRAPH_EINTERNAL). * \enumval IGRAPH_EOVERFLOW Integer or double overflow. * \enumval IGRAPH_EGLP Internal GLPK error. * \enumval IGRAPH_CPUTIME CPU time exceeded. @@ -320,9 +311,9 @@ typedef enum { IGRAPH_PARSEERROR = 3, IGRAPH_EINVAL = 4, IGRAPH_EXISTS = 5, - IGRAPH_EINVEVECTOR = 6, + /* IGRAPH_EINVEVECTOR = 6, */ /* removed in 1.0 */ IGRAPH_EINVVID = 7, - IGRAPH_NONSQUARE = 8, + IGRAPH_EINVEID = 8, /* used to be IGRAPH_NONSQUARE before 1.0 */ IGRAPH_EINVMODE = 9, IGRAPH_EFILE = 10, IGRAPH_UNIMPLEMENTED = 12, @@ -355,7 +346,7 @@ typedef enum { IGRAPH_ARPACK_MAXIT = 39, IGRAPH_ARPACK_NOSHIFT = 40, IGRAPH_ARPACK_REORDER = 41, - IGRAPH_EDIVZERO = 42, + /* IGRAPH_EDIVZERO = 42, */ /* removed in 1.0 */ IGRAPH_GLP_EBOUND = 43, IGRAPH_GLP_EROOT = 44, IGRAPH_GLP_ENOPFS = 45, @@ -364,10 +355,10 @@ typedef enum { IGRAPH_GLP_EMIPGAP = 48, IGRAPH_GLP_ETMLIM = 49, IGRAPH_GLP_ESTOP = 50, - IGRAPH_EATTRIBUTES = 51, + /* IGRAPH_EATTRIBUTES = 51, */ /* rempved in 1.0 */ IGRAPH_EATTRCOMBINE = 52, IGRAPH_ELAPACK = 53, - IGRAPH_EDRL IGRAPH_DEPRECATED_ENUMVAL = 54, + /* IGRAPH_EDRL = 54, */ /* deprecated in 0.10.2, removed in 1.0 */ IGRAPH_EOVERFLOW = 55, IGRAPH_EGLP = 56, IGRAPH_CPUTIME = 57, diff --git a/src/vendor/cigraph/include/igraph_games.h b/src/vendor/cigraph/include/igraph_games.h index e9384fd59ca..c47d8138594 100644 --- a/src/vendor/cigraph/include/igraph_games.h +++ b/src/vendor/cigraph/include/igraph_games.h @@ -52,7 +52,7 @@ IGRAPH_EXPORT igraph_error_t igraph_barabasi_game(igraph_t *graph, igraph_intege IGRAPH_EXPORT igraph_error_t igraph_erdos_renyi_game_gnp(igraph_t *graph, igraph_integer_t n, igraph_real_t p, igraph_bool_t directed, igraph_bool_t loops); IGRAPH_EXPORT igraph_error_t igraph_erdos_renyi_game_gnm(igraph_t *graph, igraph_integer_t n, igraph_integer_t m, - igraph_bool_t directed, igraph_bool_t loops); + igraph_bool_t directed, igraph_bool_t loops, igraph_bool_t multiple); IGRAPH_EXPORT igraph_error_t igraph_degree_sequence_game(igraph_t *graph, const igraph_vector_int_t *out_deg, const igraph_vector_int_t *in_deg, igraph_degseq_t method); diff --git a/src/vendor/cigraph/include/igraph_heap_pmt.h b/src/vendor/cigraph/include/igraph_heap_pmt.h index d501700d34b..45fe0cf8ee5 100644 --- a/src/vendor/cigraph/include/igraph_heap_pmt.h +++ b/src/vendor/cigraph/include/igraph_heap_pmt.h @@ -25,7 +25,6 @@ typedef struct TYPE(igraph_heap) { BASE* stor_begin; BASE* stor_end; BASE* end; - igraph_bool_t destroy; } TYPE(igraph_heap); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_heap, init)(TYPE(igraph_heap)* h, igraph_integer_t capacity); diff --git a/src/vendor/cigraph/include/igraph_interface.h b/src/vendor/cigraph/include/igraph_interface.h index 88731a39bb5..3dcdffbf7ed 100644 --- a/src/vendor/cigraph/include/igraph_interface.h +++ b/src/vendor/cigraph/include/igraph_interface.h @@ -27,6 +27,7 @@ #include "igraph_decls.h" #include "igraph_types.h" #include "igraph_datatype.h" +#include "igraph_attributes.h" #include "igraph_error.h" #include "igraph_iterators.h" @@ -37,18 +38,26 @@ __BEGIN_DECLS /* -------------------------------------------------- */ IGRAPH_EXPORT igraph_error_t igraph_empty(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed); -IGRAPH_EXPORT igraph_error_t igraph_empty_attrs(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, void *attr); +IGRAPH_EXPORT igraph_error_t igraph_empty_attrs( + igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, + const igraph_attribute_record_list_t* attr +); IGRAPH_EXPORT void igraph_destroy(igraph_t *graph); IGRAPH_EXPORT igraph_error_t igraph_copy(igraph_t *to, const igraph_t *from); -IGRAPH_EXPORT igraph_error_t igraph_add_edges(igraph_t *graph, const igraph_vector_int_t *edges, - void *attr); -IGRAPH_EXPORT igraph_error_t igraph_add_vertices(igraph_t *graph, igraph_integer_t nv, - void *attr); +IGRAPH_EXPORT igraph_error_t igraph_add_edges( + igraph_t *graph, const igraph_vector_int_t *edges, + const igraph_attribute_record_list_t* attr +); +IGRAPH_EXPORT igraph_error_t igraph_add_vertices( + igraph_t *graph, igraph_integer_t nv, + const igraph_attribute_record_list_t* attr +); IGRAPH_EXPORT igraph_error_t igraph_delete_edges(igraph_t *graph, igraph_es_t edges); IGRAPH_EXPORT igraph_error_t igraph_delete_vertices(igraph_t *graph, const igraph_vs_t vertices); -IGRAPH_EXPORT igraph_error_t igraph_delete_vertices_idx(igraph_t *graph, const igraph_vs_t vertices, - igraph_vector_int_t *idx, - igraph_vector_int_t *invidx); +IGRAPH_EXPORT igraph_error_t igraph_delete_vertices_map( + igraph_t *graph, const igraph_vs_t vertices, igraph_vector_int_t *map, + igraph_vector_int_t *invmap +); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_vcount(const igraph_t *graph); IGRAPH_EXPORT IGRAPH_FUNCATTR_PURE igraph_integer_t igraph_ecount(const igraph_t *graph); IGRAPH_EXPORT igraph_error_t igraph_neighbors(const igraph_t *graph, igraph_vector_int_t *neis, igraph_integer_t vid, @@ -134,6 +143,11 @@ IGRAPH_EXPORT void igraph_i_property_cache_invalidate_all(const igraph_t *graph) #define IGRAPH_OTHER(graph,eid,vid) \ ((igraph_integer_t)(IGRAPH_TO(graph,(eid))==(vid) ? IGRAPH_FROM((graph),(eid)) : IGRAPH_TO((graph),(eid)))) +IGRAPH_DEPRECATED IGRAPH_EXPORT igraph_error_t igraph_delete_vertices_idx( + igraph_t *graph, const igraph_vs_t vertices, igraph_vector_int_t *idx, + igraph_vector_int_t *invidx +); + __END_DECLS #endif diff --git a/src/vendor/cigraph/include/igraph_interrupt.h b/src/vendor/cigraph/include/igraph_interrupt.h index 6d8fb85ca8a..ab09df8b70c 100644 --- a/src/vendor/cigraph/include/igraph_interrupt.h +++ b/src/vendor/cigraph/include/igraph_interrupt.h @@ -26,6 +26,7 @@ #include "igraph_decls.h" #include "igraph_error.h" +#include "igraph_types.h" __BEGIN_DECLS @@ -102,11 +103,11 @@ __BEGIN_DECLS * * This is the type of the interruption handler functions. * - * \param data reserved for possible future use - * \return \c IGRAPH_SUCCESS if the calculation should go on, anything else otherwise. + * \return false if the calculation should go on, true if the calculation + * should be interrupted. */ -typedef igraph_error_t igraph_interruption_handler_t (void* data); +typedef igraph_bool_t igraph_interruption_handler_t(void); /** * \function igraph_allow_interruption @@ -115,11 +116,11 @@ typedef igraph_error_t igraph_interruption_handler_t (void* data); * \ref IGRAPH_ALLOW_INTERRUPTION macro) if \a igraph is checking for interruption * requests. * - * \param data reserved for possible future use, now it is always \c NULL - * \return \c IGRAPH_SUCCESS if the calculation should go on, anything else otherwise. + * \return false if the calculation should go on, true if the calculation + * should be interrupted. */ -IGRAPH_EXPORT igraph_error_t igraph_allow_interruption(void* data); +IGRAPH_EXPORT igraph_bool_t igraph_allow_interruption(void); IGRAPH_EXPORT igraph_interruption_handler_t * igraph_set_interruption_handler (igraph_interruption_handler_t * new_handler); diff --git a/src/vendor/cigraph/include/igraph_matrix_pmt.h b/src/vendor/cigraph/include/igraph_matrix_pmt.h index 32697530ee9..b9f73daf60e 100644 --- a/src/vendor/cigraph/include/igraph_matrix_pmt.h +++ b/src/vendor/cigraph/include/igraph_matrix_pmt.h @@ -88,7 +88,7 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, rbind)(TYPE(igraph_matrix) const TYPE(igraph_matrix) *from); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, cbind)(TYPE(igraph_matrix) *to, const TYPE(igraph_matrix) *from); -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_matrix, swap)(TYPE(igraph_matrix) *m1, TYPE(igraph_matrix) *m2); +IGRAPH_EXPORT void FUNCTION(igraph_matrix, swap)(TYPE(igraph_matrix) *m1, TYPE(igraph_matrix) *m2); /*--------------------------*/ /* Copying rows and columns */ diff --git a/src/vendor/cigraph/include/igraph_memory.h b/src/vendor/cigraph/include/igraph_memory.h index c381e3275e5..e6391cf5ba1 100644 --- a/src/vendor/cigraph/include/igraph_memory.h +++ b/src/vendor/cigraph/include/igraph_memory.h @@ -40,12 +40,6 @@ __BEGIN_DECLS #define IGRAPH_REALLOC(p,n,t) IGRAPH_I_ALLOC_CHECK_OVERFLOW(n, t, realloc((void*)(p), sizeof(t) * ((n) > 0 ? (n) : 1))) #define IGRAPH_FREE(p) (free( (void *)(p) ), (p) = NULL) -/* These are deprecated and scheduled for removal in 0.11 */ -#define igraph_Calloc IGRAPH_CALLOC -#define igraph_Realloc IGRAPH_REALLOC -#define igraph_Free IGRAPH_FREE -/* Deprecated section ends here */ - IGRAPH_EXPORT void *igraph_calloc(size_t count, size_t size); IGRAPH_EXPORT void *igraph_malloc(size_t size); IGRAPH_EXPORT void *igraph_realloc(void* ptr, size_t size); diff --git a/src/vendor/cigraph/include/igraph_misc.h b/src/vendor/cigraph/include/igraph_misc.h new file mode 100644 index 00000000000..e26f0786ad8 --- /dev/null +++ b/src/vendor/cigraph/include/igraph_misc.h @@ -0,0 +1,38 @@ +/* + IGraph library. + Copyright (C) 2003-2024 The igraph development team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* Semi-public header; not included from igraph.h. This is intentional. + * The macros defined in this header are usually not useful to the end user, + * with some exceptions like the source of the R interface. You need to + * include this header explicitly if needed. */ + +#ifndef IGRAPM_MISC_H +#define IGRAPM_MISC_H + +#include "igraph_decls.h" + +__BEGIN_DECLS + +/* Magic macro to fail the build if certain condition does not hold. See: + * https://stackoverflow.com/questions/4079243/how-can-i-use-sizeof-in-a-preprocessor-macro + */ +#define IGRAPH_STATIC_ASSERT(condition) ((void)sizeof(char[1 - 2*!(condition)])) + +__END_DECLS + +#endif diff --git a/src/vendor/cigraph/include/igraph_paths.h b/src/vendor/cigraph/include/igraph_paths.h index d0e78048b33..5c0c2a9b3e0 100644 --- a/src/vendor/cigraph/include/igraph_paths.h +++ b/src/vendor/cigraph/include/igraph_paths.h @@ -114,7 +114,8 @@ IGRAPH_EXPORT igraph_error_t igraph_distances_johnson(const igraph_t *graph, igraph_matrix_t *res, const igraph_vs_t from, const igraph_vs_t to, - const igraph_vector_t *weights); + const igraph_vector_t *weights, + igraph_neimode_t mode); IGRAPH_EXPORT igraph_error_t igraph_distances_floyd_warshall(const igraph_t *graph, igraph_matrix_t *res, igraph_vs_t from, diff --git a/src/vendor/cigraph/include/igraph_pmt.h b/src/vendor/cigraph/include/igraph_pmt.h index fe8c350d3eb..b618bcfeb60 100644 --- a/src/vendor/cigraph/include/igraph_pmt.h +++ b/src/vendor/cigraph/include/igraph_pmt.h @@ -116,6 +116,9 @@ #elif defined(BASE_GRAPH) #define BASE igraph_t +#elif defined(BASE_ATTRIBUTE_RECORD) + #define BASE igraph_attribute_record_t + #else #error unknown BASE_ directive #endif @@ -156,6 +159,10 @@ #define FUNCTION(c) CONCAT2x(igraph_graph_list,c) #define INTERNAL_FUNCTION(c) CONCAT2x(igraph_i_graph_list,c) #define TYPE igraph_graph_list_t +#elif defined(ATTRIBUTE_RECORD_LIST) + #define FUNCTION(c) CONCAT2x(igraph_attribute_record_list,c) + #define INTERNAL_FUNCTION(c) CONCAT2x(igraph_i_attribute_record_list,c) + #define TYPE igraph_attribute_record_list_t #else #if defined(BASE_IGRAPH_REAL) #define FUNCTION(a,c) CONCAT2(a,c) diff --git a/src/vendor/cigraph/include/igraph_random.h b/src/vendor/cigraph/include/igraph_random.h index fcd84f40254..be8bcbbca04 100644 --- a/src/vendor/cigraph/include/igraph_random.h +++ b/src/vendor/cigraph/include/igraph_random.h @@ -152,7 +152,7 @@ IGRAPH_EXPORT extern const igraph_rng_type_t igraph_rngtype_pcg32; IGRAPH_EXPORT extern const igraph_rng_type_t igraph_rngtype_pcg64; IGRAPH_EXPORT igraph_rng_t *igraph_rng_default(void); -IGRAPH_EXPORT void igraph_rng_set_default(igraph_rng_t *rng); +IGRAPH_EXPORT igraph_rng_t *igraph_rng_set_default(igraph_rng_t *rng); /* --------------------------------- */ diff --git a/src/vendor/cigraph/include/igraph_strvector.h b/src/vendor/cigraph/include/igraph_strvector.h index f7d2d59b90f..b3d8fa39851 100644 --- a/src/vendor/cigraph/include/igraph_strvector.h +++ b/src/vendor/cigraph/include/igraph_strvector.h @@ -37,9 +37,9 @@ __BEGIN_DECLS typedef struct s_igraph_strvector { /* Empty strings "" are represented using NULL. */ - char **stor_begin; - char **stor_end; - char **end; + const char **stor_begin; + const char **stor_end; + const char **end; } igraph_strvector_t; /** @@ -87,6 +87,9 @@ IGRAPH_EXPORT igraph_error_t igraph_strvector_append( igraph_strvector_t *to, const igraph_strvector_t *from); IGRAPH_EXPORT igraph_error_t igraph_strvector_merge( igraph_strvector_t *to, igraph_strvector_t *from); +IGRAPH_EXPORT void igraph_strvector_swap(igraph_strvector_t *v1, igraph_strvector_t *v2); +IGRAPH_EXPORT igraph_error_t igraph_strvector_update( + igraph_strvector_t *to, const igraph_strvector_t *from); IGRAPH_EXPORT igraph_error_t igraph_strvector_resize( igraph_strvector_t* v, igraph_integer_t newsize); IGRAPH_EXPORT igraph_error_t igraph_strvector_push_back(igraph_strvector_t *v, diff --git a/src/vendor/cigraph/include/igraph_topology.h b/src/vendor/cigraph/include/igraph_topology.h index 3afd1e4f5cf..b217033fc17 100644 --- a/src/vendor/cigraph/include/igraph_topology.h +++ b/src/vendor/cigraph/include/igraph_topology.h @@ -57,6 +57,17 @@ IGRAPH_EXPORT igraph_error_t igraph_isomorphic(const igraph_t *graph1, const igr igraph_bool_t *iso); IGRAPH_EXPORT igraph_error_t igraph_subisomorphic(const igraph_t *graph1, const igraph_t *graph2, igraph_bool_t *iso); +IGRAPH_EXPORT igraph_error_t igraph_count_automorphisms( + const igraph_t *graph, const igraph_vector_int_t *colors, + igraph_real_t *result); +IGRAPH_EXPORT igraph_error_t igraph_automorphism_group( + const igraph_t *graph, const igraph_vector_int_t *colors, + igraph_vector_int_list_t *generators +); +IGRAPH_EXPORT igraph_error_t igraph_canonical_permutation( + const igraph_t *graph, const igraph_vector_int_t *colors, + igraph_vector_int_t *labeling +); /* LAD */ IGRAPH_EXPORT igraph_error_t igraph_subisomorphic_lad( @@ -264,7 +275,7 @@ typedef struct igraph_bliss_info_t { * \enumval IGRAPH_BLISS_FLM Largest maximally non-trivially connected * non-singleton cell. * \enumval IGRAPH_BLISS_FSM Smallest maximally non-trivially - * connected non-singletion cell. + * connected non-singleton cell. */ typedef enum { IGRAPH_BLISS_F = 0, IGRAPH_BLISS_FL, @@ -272,7 +283,7 @@ typedef enum { IGRAPH_BLISS_F = 0, IGRAPH_BLISS_FL, IGRAPH_BLISS_FLM, IGRAPH_BLISS_FSM } igraph_bliss_sh_t; -IGRAPH_EXPORT igraph_error_t igraph_canonical_permutation(const igraph_t *graph, const igraph_vector_int_t *colors, igraph_vector_int_t *labeling, +IGRAPH_EXPORT igraph_error_t igraph_canonical_permutation_bliss(const igraph_t *graph, const igraph_vector_int_t *colors, igraph_vector_int_t *labeling, igraph_bliss_sh_t sh, igraph_bliss_info_t *info); IGRAPH_EXPORT igraph_error_t igraph_isomorphic_bliss(const igraph_t *graph1, const igraph_t *graph2, const igraph_vector_int_t *colors1, const igraph_vector_int_t *colors2, @@ -281,15 +292,10 @@ IGRAPH_EXPORT igraph_error_t igraph_isomorphic_bliss(const igraph_t *graph1, con igraph_bliss_sh_t sh, igraph_bliss_info_t *info1, igraph_bliss_info_t *info2); -IGRAPH_EXPORT igraph_error_t igraph_count_automorphisms( - const igraph_t *graph, const igraph_vector_int_t *colors, - igraph_bliss_sh_t sh, igraph_bliss_info_t *info); - -IGRAPH_EXPORT IGRAPH_DEPRECATED igraph_error_t igraph_automorphisms( +IGRAPH_EXPORT igraph_error_t igraph_count_automorphisms_bliss( const igraph_t *graph, const igraph_vector_int_t *colors, igraph_bliss_sh_t sh, igraph_bliss_info_t *info); - -IGRAPH_EXPORT igraph_error_t igraph_automorphism_group( +IGRAPH_EXPORT igraph_error_t igraph_automorphism_group_bliss( const igraph_t *graph, const igraph_vector_int_t *colors, igraph_vector_int_list_t *generators, igraph_bliss_sh_t sh, igraph_bliss_info_t *info diff --git a/src/vendor/cigraph/include/igraph_typed_list_pmt.h b/src/vendor/cigraph/include/igraph_typed_list_pmt.h index 2110d5558d1..85731d9b566 100644 --- a/src/vendor/cigraph/include/igraph_typed_list_pmt.h +++ b/src/vendor/cigraph/include/igraph_typed_list_pmt.h @@ -51,6 +51,7 @@ typedef struct { /*--------------------*/ IGRAPH_EXPORT igraph_error_t FUNCTION(init)(TYPE* v, igraph_integer_t size); +IGRAPH_EXPORT igraph_error_t FUNCTION(init_copy)(TYPE* to, const TYPE* from); IGRAPH_EXPORT void FUNCTION(destroy)(TYPE* v); /*--------------------*/ diff --git a/src/vendor/cigraph/include/igraph_vector_pmt.h b/src/vendor/cigraph/include/igraph_vector_pmt.h index d324fece262..7772f73a209 100644 --- a/src/vendor/cigraph/include/igraph_vector_pmt.h +++ b/src/vendor/cigraph/include/igraph_vector_pmt.h @@ -103,7 +103,7 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, update)(TYPE(igraph_vector) const TYPE(igraph_vector) *from); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, append)(TYPE(igraph_vector) *to, const TYPE(igraph_vector) *from); -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, swap)(TYPE(igraph_vector) *v1, TYPE(igraph_vector) *v2); +IGRAPH_EXPORT void FUNCTION(igraph_vector, swap)(TYPE(igraph_vector) *v1, TYPE(igraph_vector) *v2); /*-----------------------*/ /* Exchanging elements */ @@ -114,7 +114,7 @@ IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, swap_elements)( IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, reverse)(TYPE(igraph_vector) *v); IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, permute)(TYPE(igraph_vector) *v, const igraph_vector_int_t *ind); -IGRAPH_EXPORT igraph_error_t FUNCTION(igraph_vector, shuffle)(TYPE(igraph_vector) *v); +IGRAPH_EXPORT void FUNCTION(igraph_vector, shuffle)(TYPE(igraph_vector) *v); /*-----------------------*/ /* Vector operations */ diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml index d3e04847000..1eec57e43df 100644 --- a/src/vendor/cigraph/interfaces/functions.yaml +++ b/src/vendor/cigraph/interfaces/functions.yaml @@ -34,7 +34,7 @@ igraph_delete_vertices: PARAMS: INOUT GRAPH graph, VERTEX_SELECTOR vertices DEPS: vertices ON graph -igraph_delete_vertices_idx: +igraph_delete_vertices_map: PARAMS: |- INOUT GRAPH graph, VERTEX_SELECTOR vertices, OPTIONAL OUT VECTOR_INT idx, @@ -113,12 +113,12 @@ igraph_sparse_weighted_adjacency: # construction to eliminate duplicate elements from the representation PARAMS: |- OUT GRAPH graph, INOUT SPARSEMAT adjmatrix, ADJACENCY_MODE mode=DIRECTED, - OUT EDGEWEIGHTS weights, LOOPS loops=ONCE + OUT EDGE_WEIGHTS weights, LOOPS loops=ONCE igraph_weighted_adjacency: PARAMS: |- OUT GRAPH graph, MATRIX adjmatrix, ADJACENCY_MODE mode=DIRECTED, - OUT EDGEWEIGHTS weights, LOOPS loops=ONCE + OUT EDGE_WEIGHTS weights, LOOPS loops=ONCE igraph_star: PARAMS: OUT GRAPH graph, INTEGER n, STAR_MODE mode=OUT, INTEGER center=0 @@ -236,7 +236,7 @@ igraph_erdos_renyi_game_gnp: PARAMS: OUT GRAPH graph, INTEGER n, REAL p, BOOLEAN directed=False, BOOLEAN loops=False igraph_erdos_renyi_game_gnm: - PARAMS: OUT GRAPH graph, INTEGER n, INTEGER m, BOOLEAN directed=False, BOOLEAN loops=False + PARAMS: OUT GRAPH graph, INTEGER n, INTEGER m, BOOLEAN directed=False, BOOLEAN loops=False, BOOLEAN multiple=False igraph_degree_sequence_game: PARAMS: |- @@ -426,7 +426,7 @@ igraph_diameter: igraph_diameter_dijkstra: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, + GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT REAL res, OUT INTEGER from, OUT INTEGER to, OPTIONAL OUT VECTOR_INT vertex_path, OPTIONAL OUT VECTOR_INT edge_path, @@ -435,21 +435,21 @@ igraph_diameter_dijkstra: igraph_closeness: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, + GRAPH graph, OUT VERTEX_QTYS res, OPTIONAL OUT VECTOR_INT reachable_count, OPTIONAL OUT BOOLEAN all_reachable, VERTEX_SELECTOR vids=ALL, - NEIMODE mode=OUT, EDGEWEIGHTS weights=NULL, + NEIMODE mode=OUT, EDGE_WEIGHTS weights=NULL, BOOLEAN normalized=False DEPS: vids ON graph, weights ON graph, res ON graph vids igraph_closeness_cutoff: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, + GRAPH graph, OUT VERTEX_QTYS res, OPTIONAL OUT VECTOR_INT reachable_count, OPTIONAL OUT BOOLEAN all_reachable, VERTEX_SELECTOR vids=ALL, - NEIMODE mode=OUT, EDGEWEIGHTS weights=NULL, + NEIMODE mode=OUT, EDGE_WEIGHTS weights=NULL, BOOLEAN normalized=False, REAL cutoff=-1 DEPS: vids ON graph, weights ON graph, res ON graph vids @@ -476,28 +476,28 @@ igraph_get_shortest_path_bellman_ford: PARAMS: |- GRAPH graph, OPTIONAL OUT VERTEX_INDICES vertices, OPTIONAL OUT EDGE_INDICES edges, - VERTEX from, VERTEX to, OPTIONAL EDGEWEIGHTS weights=NULL, NEIMODE mode=OUT + VERTEX from, VERTEX to, OPTIONAL EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT DEPS: from ON graph, to ON graph, weights ON graph, vertices ON graph, edges ON graph igraph_get_shortest_path_dijkstra: PARAMS: |- GRAPH graph, OPTIONAL OUT VERTEX_INDICES vertices, OPTIONAL OUT EDGE_INDICES edges, - VERTEX from, VERTEX to, OPTIONAL EDGEWEIGHTS weights=NULL, NEIMODE mode=OUT + VERTEX from, VERTEX to, OPTIONAL EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT DEPS: from ON graph, to ON graph, weights ON graph, vertices ON graph, edges ON graph igraph_get_shortest_path_astar: PARAMS: |- GRAPH graph, OPTIONAL OUT VERTEX_INDICES vertices, OPTIONAL OUT EDGE_INDICES edges, - VERTEX from, VERTEX to, OPTIONAL EDGEWEIGHTS weights=NULL, NEIMODE mode=OUT, + VERTEX from, VERTEX to, OPTIONAL EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT, OPTIONAL ASTAR_HEURISTIC_FUNC heuristic=NULL, EXTRA extra=NULL DEPS: from ON graph, to ON graph, weights ON graph, vertices ON graph, edges ON graph igraph_get_shortest_paths: PARAMS: |- GRAPH graph, - OPTIONAL OUT VERTEXSET_LIST vertices, OPTIONAL OUT EDGESET_LIST edges, + OPTIONAL OUT VERTEX_INDICES_LIST vertices, OPTIONAL OUT EDGE_INDICES_LIST edges, VERTEX from, VERTEX_SELECTOR to=ALL, NEIMODE mode=OUT, OPTIONAL OUT VECTOR_INT parents, OPTIONAL OUT VECTOR_INT inbound_edges @@ -505,28 +505,28 @@ igraph_get_shortest_paths: igraph_get_all_shortest_paths: PARAMS: |- - GRAPH graph, OPTIONAL OUT VERTEXSET_LIST vertices, - OPTIONAL OUT EDGESET_LIST edges, OPTIONAL OUT VECTOR_INT nrgeo, + GRAPH graph, OPTIONAL OUT VERTEX_INDICES_LIST vertices, + OPTIONAL OUT EDGE_INDICES_LIST edges, OPTIONAL OUT VECTOR_INT nrgeo, VERTEX from, VERTEX_SELECTOR to, NEIMODE mode=OUT DEPS: edges ON graph, from ON graph, to ON graph igraph_distances_dijkstra: PARAMS: |- GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, EDGEWEIGHTS weights, NEIMODE mode=OUT + VERTEX_SELECTOR to=ALL, EDGE_WEIGHTS weights, NEIMODE mode=OUT DEPS: from ON graph, to ON graph, weights ON graph igraph_distances_dijkstra_cutoff: PARAMS: |- GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, EDGEWEIGHTS weights, NEIMODE mode=OUT, REAL cutoff=-1 + VERTEX_SELECTOR to=ALL, EDGE_WEIGHTS weights, NEIMODE mode=OUT, REAL cutoff=-1 DEPS: from ON graph, to ON graph, weights ON graph igraph_get_shortest_paths_dijkstra: PARAMS: |- - GRAPH graph, OPTIONAL OUT VERTEXSET_LIST vertices, - OPTIONAL OUT EDGESET_LIST edges, VERTEX from, VERTEX_SELECTOR to=ALL, - EDGEWEIGHTS weights=NULL, NEIMODE mode=OUT, + GRAPH graph, OPTIONAL OUT VERTEX_INDICES_LIST vertices, + OPTIONAL OUT EDGE_INDICES_LIST edges, VERTEX from, VERTEX_SELECTOR to=ALL, + EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT, OPTIONAL OUT VECTOR_INT parents=0, OPTIONAL OUT VECTOR_INT inbound_edges=0 DEPS: |- @@ -535,9 +535,9 @@ igraph_get_shortest_paths_dijkstra: igraph_get_shortest_paths_bellman_ford: PARAMS: |- - GRAPH graph, OPTIONAL OUT VERTEXSET_LIST vertices, - OPTIONAL OUT EDGESET_LIST edges, VERTEX from, VERTEX_SELECTOR to=ALL, - EDGEWEIGHTS weights=NULL, NEIMODE mode=OUT, + GRAPH graph, OPTIONAL OUT VERTEX_INDICES_LIST vertices, + OPTIONAL OUT EDGE_INDICES_LIST edges, VERTEX from, VERTEX_SELECTOR to=ALL, + EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT, OPTIONAL OUT VECTOR_INT parents=0, OPTIONAL OUT VECTOR_INT inbound_edges=0 DEPS: |- @@ -546,9 +546,9 @@ igraph_get_shortest_paths_bellman_ford: igraph_get_all_shortest_paths_dijkstra: PARAMS: |- - GRAPH graph, OPTIONAL OUT VERTEXSET_LIST vertices, - OPTIONAL OUT EDGESET_LIST edges, OPTIONAL OUT VECTOR_INT nrgeo, - VERTEX from, VERTEX_SELECTOR to=ALL, EDGEWEIGHTS weights, + GRAPH graph, OPTIONAL OUT VERTEX_INDICES_LIST vertices, + OPTIONAL OUT EDGE_INDICES_LIST edges, OPTIONAL OUT VECTOR_INT nrgeo, + VERTEX from, VERTEX_SELECTOR to=ALL, EDGE_WEIGHTS weights, NEIMODE mode=OUT DEPS: |- weights ON graph, from ON graph, to ON graph, vertices ON graph, edges ON graph @@ -556,26 +556,26 @@ igraph_get_all_shortest_paths_dijkstra: igraph_distances_bellman_ford: PARAMS: |- GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, EDGEWEIGHTS weights, NEIMODE mode=OUT + VERTEX_SELECTOR to=ALL, EDGE_WEIGHTS weights, NEIMODE mode=OUT DEPS: from ON graph, to ON graph, weights ON graph igraph_distances_johnson: PARAMS: |- GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, EDGEWEIGHTS weights + VERTEX_SELECTOR to=ALL, EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT DEPS: from ON graph, to ON graph, weights ON graph igraph_distances_floyd_warshall: PARAMS: |- GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, EDGEWEIGHTS weights=NULL, NEIMODE mode=OUT, + VERTEX_SELECTOR to=ALL, EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT, FWALGORITHM method DEPS: from ON graph, to ON graph, weights ON graph igraph_voronoi: PARAMS: |- GRAPH graph, OUT VECTOR_INT membership, OUT VECTOR distances, - VERTEX_INDICES generators, EDGEWEIGHTS weights=NULL, NEIMODE mode=OUT, VORONOI_TIEBREAKER tiebreaker=RANDOM + VERTEX_INDICES generators, EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT, VORONOI_TIEBREAKER tiebreaker=RANDOM DEPS: weights ON graph, generators ON graph igraph_get_all_simple_paths: @@ -586,9 +586,9 @@ igraph_get_all_simple_paths: igraph_get_k_shortest_paths: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, - OPTIONAL OUT VERTEXSET_LIST vertex_paths, - OPTIONAL OUT EDGESET_LIST edge_paths, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + OPTIONAL OUT VERTEX_INDICES_LIST vertex_paths, + OPTIONAL OUT EDGE_INDICES_LIST edge_paths, INTEGER k, VERTEX from, VERTEX to, NEIMODE mode=OUT DEPS: |- from ON graph, to ON graph, weights ON graph, vertex_paths ON graph, edge_paths ON graph @@ -597,15 +597,15 @@ igraph_get_widest_path: PARAMS: |- GRAPH graph, OPTIONAL OUT VERTEX_INDICES vertices, OPTIONAL OUT EDGE_INDICES edges, - VERTEX from, VERTEX to, EDGEWEIGHTS weights=NULL, NEIMODE mode=OUT + VERTEX from, VERTEX to, EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT DEPS: |- from ON graph, to ON graph, weights ON graph, vertices ON graph, edges ON graph igraph_get_widest_paths: PARAMS: |- GRAPH graph, - OPTIONAL OUT VERTEXSET_LIST vertices, OPTIONAL OUT EDGESET_LIST edges, - VERTEX from, VERTEX_SELECTOR to=ALL, EDGEWEIGHTS weights=NULL, + OPTIONAL OUT VERTEX_INDICES_LIST vertices, OPTIONAL OUT EDGE_INDICES_LIST edges, + VERTEX from, VERTEX_SELECTOR to=ALL, EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT, OPTIONAL OUT VECTOR_INT parents, OPTIONAL OUT VECTOR_INT inbound_edges DEPS: |- @@ -615,18 +615,18 @@ igraph_get_widest_paths: igraph_widest_path_widths_dijkstra: PARAMS: |- GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, EDGEWEIGHTS weights, NEIMODE mode=OUT + VERTEX_SELECTOR to=ALL, EDGE_WEIGHTS weights, NEIMODE mode=OUT DEPS: from ON graph, to ON graph, weights ON graph igraph_widest_path_widths_floyd_warshall: PARAMS: |- GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR from=ALL, - VERTEX_SELECTOR to=ALL, EDGEWEIGHTS weights, NEIMODE mode=OUT + VERTEX_SELECTOR to=ALL, EDGE_WEIGHTS weights, NEIMODE mode=OUT DEPS: from ON graph, to ON graph, weights ON graph igraph_spanner: PARAMS: |- - GRAPH graph, OUT EDGE_INDICES spanner, REAL stretch, OPTIONAL EDGEWEIGHTS weights + GRAPH graph, OUT EDGE_INDICES spanner, REAL stretch, OPTIONAL EDGE_WEIGHTS weights DEPS: weights ON graph igraph_subcomponent: @@ -635,64 +635,64 @@ igraph_subcomponent: igraph_betweenness: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - BOOLEAN directed=True, EDGEWEIGHTS weights=NULL + GRAPH graph, OUT VERTEX_QTYS res, VERTEX_SELECTOR vids=ALL, + BOOLEAN directed=True, EDGE_WEIGHTS weights=NULL DEPS: weights ON graph, vids ON graph, res ON graph vids igraph_betweenness_cutoff: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - BOOLEAN directed=True, EDGEWEIGHTS weights=NULL, + GRAPH graph, OUT VERTEX_QTYS res, VERTEX_SELECTOR vids=ALL, + BOOLEAN directed=True, EDGE_WEIGHTS weights=NULL, REAL cutoff=-1 DEPS: vids ON graph, weights ON graph, res ON graph vids igraph_betweenness_subset: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, + GRAPH graph, OUT VERTEX_QTYS res, VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, VERTEX_SELECTOR sources=ALL, VERTEX_SELECTOR targets=ALL, - EDGEWEIGHTS weights=NULL + EDGE_WEIGHTS weights=NULL DEPS: |- vids ON graph, weights ON graph, res ON graph, sources ON graph, targets ON graph igraph_edge_betweenness: PARAMS: |- GRAPH graph, OUT VECTOR res, BOOLEAN directed=True, - EDGEWEIGHTS weights=NULL + EDGE_WEIGHTS weights=NULL DEPS: weights ON graph igraph_edge_betweenness_cutoff: PARAMS: |- GRAPH graph, OUT VECTOR res, BOOLEAN directed=True, - EDGEWEIGHTS weights=NULL, REAL cutoff=-1 + EDGE_WEIGHTS weights=NULL, REAL cutoff=-1 DEPS: weights ON graph igraph_edge_betweenness_subset: PARAMS: |- - GRAPH graph, OUT VECTOR res, EDGE_SELECTOR eids=ALL, + GRAPH graph, OUT VERTEX_QTYS res, EDGE_SELECTOR eids=ALL, BOOLEAN directed=True, VERTEX_SELECTOR sources=ALL, VERTEX_SELECTOR targets=ALL, - EDGEWEIGHTS weights=NULL + EDGE_WEIGHTS weights=NULL DEPS: |- eids ON graph, weights ON graph, res ON graph, sources ON graph, targets ON graph igraph_harmonic_centrality: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - NEIMODE mode=OUT, EDGEWEIGHTS weights=NULL, BOOLEAN normalized=False + GRAPH graph, OUT VERTEX_QTYS res, VERTEX_SELECTOR vids=ALL, + NEIMODE mode=OUT, EDGE_WEIGHTS weights=NULL, BOOLEAN normalized=False DEPS: weights ON graph, vids ON graph, res ON graph vids igraph_harmonic_centrality_cutoff: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - NEIMODE mode=OUT, EDGEWEIGHTS weights=NULL, BOOLEAN normalized=False, + GRAPH graph, OUT VERTEX_QTYS res, VERTEX_SELECTOR vids=ALL, + NEIMODE mode=OUT, EDGE_WEIGHTS weights=NULL, BOOLEAN normalized=False, REAL cutoff=-1 DEPS: vids ON graph, weights ON graph, res ON graph vids igraph_pagerank: PARAMS: |- GRAPH graph, PAGERANKALGO algo=PRPACK, - OUT VERTEX_QTY vector, OUT REAL value, + OUT VERTEX_QTYS vector, OUT REAL value, VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, - REAL damping=0.85, EDGEWEIGHTS weights=NULL, + REAL damping=0.85, EDGE_WEIGHTS weights=NULL, INOUT PAGERANKOPT options=NULL DEPS: |- vids ON graph, weights ON graph, vector ON graph, @@ -701,10 +701,10 @@ igraph_pagerank: igraph_personalized_pagerank: PARAMS: |- GRAPH graph, PAGERANKALGO algo=PRPACK, - OUT VERTEX_QTY vector, OUT REAL value, + OUT VERTEX_QTYS vector, OUT REAL value, VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, REAL damping=0.85, OPTIONAL VECTOR personalized, - OPTIONAL EDGEWEIGHTS weights, + OPTIONAL EDGE_WEIGHTS weights, INOUT PAGERANKOPT options=NULL DEPS: |- vids ON graph, weights ON graph, vector ON graph vids, @@ -713,11 +713,11 @@ igraph_personalized_pagerank: igraph_personalized_pagerank_vs: PARAMS: |- GRAPH graph, PAGERANKALGO algo=PRPACK, - PRIMARY OUT VERTEX_QTY vector, OUT REAL value, + PRIMARY OUT VERTEX_QTYS vector, OUT REAL value, VERTEX_SELECTOR vids=ALL, BOOLEAN directed=True, REAL damping=0.85, VERTEX_SELECTOR reset_vids, - OPTIONAL EDGEWEIGHTS weights=NULL, + OPTIONAL EDGE_WEIGHTS weights=NULL, INOUT PAGERANKOPT options=NULL DEPS: |- vids ON graph, weights ON graph, vector ON graph vids, @@ -744,7 +744,7 @@ igraph_average_path_length: igraph_average_path_length_dijkstra: PARAMS: GRAPH graph, PRIMARY OUT REAL res, OUT REAL unconn_pairs=NULL, - EDGEWEIGHTS weights=NULL, BOOLEAN directed=True, BOOLEAN unconn=True + EDGE_WEIGHTS weights=NULL, BOOLEAN directed=True, BOOLEAN unconn=True DEPS: weights ON graph igraph_path_length_hist: @@ -771,7 +771,7 @@ igraph_transitivity_avglocal_undirected: igraph_transitivity_barrat: PARAMS: |- GRAPH graph, OUT VECTOR res, VERTEX_SELECTOR vids=ALL, - EDGEWEIGHTS weights=NULL, TRANSITIVITY_MODE mode=NAN + EDGE_WEIGHTS weights=NULL, TRANSITIVITY_MODE mode=NAN DEPS: res ON graph, vids ON graph, weights ON graph igraph_ecc: @@ -786,7 +786,7 @@ igraph_reciprocity: RECIP mode=DEFAULT igraph_constraint: - PARAMS: GRAPH graph, OUT VECTOR res, VERTEX_SELECTOR vids=ALL, OPTIONAL EDGEWEIGHTS weights + PARAMS: GRAPH graph, OUT VECTOR res, VERTEX_SELECTOR vids=ALL, OPTIONAL EDGE_WEIGHTS weights DEPS: vids ON graph, weights ON graph igraph_maxdegree: @@ -806,7 +806,7 @@ igraph_neighborhood_size: igraph_neighborhood: PARAMS: |- - GRAPH graph, OUT VERTEXSET_LIST res, + GRAPH graph, OUT VERTEX_INDICES_LIST res, VERTEX_SELECTOR vids, INTEGER order, NEIMODE mode=ALL, INTEGER mindist=0 DEPS: res ON graph, vids ON graph @@ -824,7 +824,7 @@ igraph_topological_sorting: igraph_feedback_arc_set: # Default algorithm is the approximate method because it is faster and the # function is _not_ called igraph_minimum_feedback_arc_set - PARAMS: GRAPH graph, OUT EDGE_INDICES result, EDGEWEIGHTS weights=NULL, FAS_ALGORITHM algo=APPROX_EADES + PARAMS: GRAPH graph, OUT EDGE_INDICES result, EDGE_WEIGHTS weights=NULL, FAS_ALGORITHM algo=APPROX_EADES DEPS: result ON graph, weights ON graph igraph_is_loop: @@ -866,31 +866,31 @@ igraph_add_edge: igraph_eigenvector_centrality: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY vector, OUT REAL value, + GRAPH graph, OUT VERTEX_QTYS vector, OUT REAL value, BOOLEAN directed=False, BOOLEAN scale=True, - EDGEWEIGHTS weights=NULL, - INOUT ARPACKOPT options=ARPACK_DEFAULTS + EDGE_WEIGHTS weights=NULL, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS DEPS: weights ON graph, vector ON graph igraph_hub_score: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY vector, OUT REAL value, - BOOLEAN scale=True, EDGEWEIGHTS weights=NULL, - INOUT ARPACKOPT options=ARPACK_DEFAULTS + GRAPH graph, OUT VERTEX_QTYS vector, OUT REAL value, + BOOLEAN scale=True, EDGE_WEIGHTS weights=NULL, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS DEPS: weights ON graph, vector ON graph igraph_authority_score: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY vector, OUT REAL value, - BOOLEAN scale=True, EDGEWEIGHTS weights=NULL, - INOUT ARPACKOPT options=ARPACK_DEFAULTS + GRAPH graph, OUT VERTEX_QTYS vector, OUT REAL value, + BOOLEAN scale=True, EDGE_WEIGHTS weights=NULL, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS DEPS: weights ON graph, vector ON graph igraph_hub_and_authority_scores: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY hub_vector, OUT VERTEX_QTY authority_vector, - OUT REAL value, BOOLEAN scale=True, EDGEWEIGHTS weights=NULL, - INOUT ARPACKOPT options=ARPACK_DEFAULTS + GRAPH graph, OUT VERTEX_QTYS hub_vector, OUT VERTEX_QTYS authority_vector, + OUT REAL value, BOOLEAN scale=True, EDGE_WEIGHTS weights=NULL, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS igraph_unfold_tree: PARAMS: |- @@ -919,13 +919,13 @@ igraph_avg_nearest_neighbor_degree: PARAMS: |- GRAPH graph, VERTEX_SELECTOR vids=ALL, NEIMODE mode=ALL, NEIMODE neighbor_degree_mode=ALL, - OPTIONAL OUT VERTEX_QTY knn, OPTIONAL OUT VECTOR knnk, - EDGEWEIGHTS weights=NULL + OPTIONAL OUT VERTEX_QTYS knn, OPTIONAL OUT VECTOR knnk, + EDGE_WEIGHTS weights=NULL DEPS: vids ON graph, weights ON graph, knn ON graph vids igraph_degree_correlation_vector: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, + GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT VECTOR knnk, NEIMODE from_mode=OUT, NEIMODE to_mode=IN, BOOLEAN directed_neighbors=True @@ -933,8 +933,8 @@ igraph_degree_correlation_vector: igraph_strength: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - NEIMODE mode=ALL, BOOLEAN loops=True, EDGEWEIGHTS weights=NULL + GRAPH graph, OUT VERTEX_QTYS res, VERTEX_SELECTOR vids=ALL, + NEIMODE mode=ALL, BOOLEAN loops=True, EDGE_WEIGHTS weights=NULL DEPS: vids ON graph, weights ON graph, res ON graph vids igraph_centralization: @@ -985,7 +985,7 @@ igraph_centralization_eigenvector_centrality: PARAMS: |- GRAPH graph, OUT VECTOR vector, OUT REAL value, BOOLEAN directed=False, BOOLEAN scale=True, - INOUT ARPACKOPT options=ARPACK_DEFAULTS, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS, OUT REAL centralization, OUT REAL theoretical_max, BOOLEAN normalized=True @@ -1010,14 +1010,14 @@ igraph_assortativity_degree: igraph_joint_degree_matrix: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, + GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT MATRIX jdm, INTEGER max_out_degree=-1, INTEGER max_in_degree=-1 DEPS: weights ON graph igraph_joint_degree_distribution: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, + GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT MATRIX p, NEIMODE from_mode=OUT, NEIMODE to_mode=IN, BOOLEAN directed_neighbors=True, @@ -1027,7 +1027,7 @@ igraph_joint_degree_distribution: igraph_joint_type_distribution: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, + GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT MATRIX p, INDEX_VECTOR from_types, INDEX_VECTOR to_types=NULL, BOOLEAN directed=True, @@ -1041,14 +1041,14 @@ igraph_contract_vertices: igraph_eccentricity: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, + GRAPH graph, OUT VERTEX_QTYS res, VERTEX_SELECTOR vids=ALL, NEIMODE mode=ALL DEPS: vids ON graph, res ON graph vids igraph_eccentricity_dijkstra: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, - OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, + GRAPH graph, EDGE_WEIGHTS weights=NULL, + OUT VERTEX_QTYS res, VERTEX_SELECTOR vids=ALL, NEIMODE mode=ALL DEPS: weights ON graph, vids ON graph, res ON graph vids @@ -1059,14 +1059,14 @@ igraph_graph_center: igraph_graph_center_dijkstra: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, OUT VERTEX_INDICES res, NEIMODE mode=ALL + GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT VERTEX_INDICES res, NEIMODE mode=ALL DEPS: weights ON graph, res ON graph igraph_radius: PARAMS: GRAPH graph, OUT REAL radius, NEIMODE mode=ALL igraph_radius_dijkstra: - PARAMS: GRAPH graph, EDGEWEIGHTS weights=NULL, OUT REAL radius, NEIMODE mode=ALL + PARAMS: GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT REAL radius, NEIMODE mode=ALL DEPS: weights ON graph igraph_pseudo_diameter: @@ -1077,7 +1077,7 @@ igraph_pseudo_diameter: igraph_pseudo_diameter_dijkstra: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, + GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT REAL diameter, VERTEX start_vid, OUT INTEGER from=NULL, OUT INTEGER to=NULL, BOOLEAN directed=True, BOOLEAN unconnected=True @@ -1085,35 +1085,35 @@ igraph_pseudo_diameter_dijkstra: igraph_diversity: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, OUT VERTEX_QTY res, + GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT VERTEX_QTYS res, VERTEX_SELECTOR vids=ALL DEPS: weights ON graph, vids ON graph, res ON graph vids igraph_random_walk: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, OUT VERTEX_INDICES vertices, OUT EDGE_INDICES edges, + GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT VERTEX_INDICES vertices, OUT EDGE_INDICES edges, VERTEX start, NEIMODE mode=OUT, INTEGER steps, RWSTUCK stuck=RETURN DEPS: start ON graph, weights ON graph, vertices ON graph, edges ON graph igraph_random_edge_walk: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, OUT EDGE_INDICES edgewalk, + GRAPH graph, EDGE_WEIGHTS weights=NULL, OUT EDGE_INDICES edgewalk, VERTEX start, NEIMODE mode=OUT, INTEGER steps, RWSTUCK stuck=RETURN DEPS: start ON graph, weights ON graph, edgewalk ON graph igraph_global_efficiency: - PARAMS: GRAPH graph, OUT REAL res, EDGEWEIGHTS weights=NULL, BOOLEAN directed=True + PARAMS: GRAPH graph, OUT REAL res, EDGE_WEIGHTS weights=NULL, BOOLEAN directed=True DEPS: weights ON graph igraph_local_efficiency: PARAMS: |- - GRAPH graph, OUT VERTEX_QTY res, VERTEX_SELECTOR vids=ALL, - EDGEWEIGHTS weights=NULL, BOOLEAN directed=True, NEIMODE mode=ALL + GRAPH graph, OUT VERTEX_QTYS res, VERTEX_SELECTOR vids=ALL, + EDGE_WEIGHTS weights=NULL, BOOLEAN directed=True, NEIMODE mode=ALL DEPS: vids ON graph, weights ON graph, res ON graph vids igraph_average_local_efficiency: PARAMS: |- - GRAPH graph, OUT REAL res, EDGEWEIGHTS weights=NULL, + GRAPH graph, OUT REAL res, EDGE_WEIGHTS weights=NULL, BOOLEAN directed=True, NEIMODE mode=ALL DEPS: weights ON graph @@ -1215,7 +1215,7 @@ igraph_bipartite_game_gnm: PARAMS: |- OUT GRAPH graph, OPTIONAL OUT BIPARTITE_TYPES types, INTEGER n1, INTEGER n2, INTEGER m, BOOLEAN directed=False, - NEIMODE mode=ALL + NEIMODE mode=ALL, BOOLEAN multiple=False igraph_bipartite_game: PARAMS: |- @@ -1231,13 +1231,13 @@ igraph_bipartite_game: igraph_get_laplacian: PARAMS: |- GRAPH graph, OUT MATRIX res, NEIMODE mode=OUT, - LAPLACIAN_NORMALIZATION normalization=UNNORMALIZED, EDGEWEIGHTS weights=NULL + LAPLACIAN_NORMALIZATION normalization=UNNORMALIZED, EDGE_WEIGHTS weights=NULL DEPS: weights ON graph igraph_get_laplacian_sparse: PARAMS: |- GRAPH graph, OUT SPARSEMAT sparseres, NEIMODE mode=OUT, - LAPLACIAN_NORMALIZATION normalization=UNNORMALIZED, EDGEWEIGHTS weights=NULL + LAPLACIAN_NORMALIZATION normalization=UNNORMALIZED, EDGE_WEIGHTS weights=NULL DEPS: weights ON graph ####################################### @@ -1264,9 +1264,9 @@ igraph_articulation_points: igraph_biconnected_components: PARAMS: |- GRAPH graph, OUT INTEGER no, - OPTIONAL OUT EDGESET_LIST tree_edges, - OPTIONAL OUT EDGESET_LIST component_edges, - OPTIONAL OUT VERTEXSET_LIST components, + OPTIONAL OUT EDGE_INDICES_LIST tree_edges, + OPTIONAL OUT EDGE_INDICES_LIST component_edges, + OPTIONAL OUT VERTEX_INDICES_LIST components, OUT VERTEX_INDICES articulation_points DEPS: |- tree_edges ON graph, component_edges ON graph, @@ -1285,7 +1285,7 @@ igraph_is_biconnected: igraph_cliques: PARAMS: |- - GRAPH graph, OUT VERTEXSET_LIST res, INTEGER min_size=0, + GRAPH graph, OUT VERTEX_INDICES_LIST res, INTEGER min_size=0, INTEGER max_size=0 DEPS: res ON graph @@ -1299,16 +1299,16 @@ igraph_clique_size_hist: GRAPH graph, OUT VECTOR hist, INTEGER min_size=0, INTEGER max_size=0 igraph_largest_cliques: - PARAMS: GRAPH graph, OUT VERTEXSET_LIST res + PARAMS: GRAPH graph, OUT VERTEX_INDICES_LIST res DEPS: res ON graph igraph_maximal_cliques: - PARAMS: GRAPH graph, OUT VERTEXSET_LIST res, INTEGER min_size=0, INTEGER max_size=0 + PARAMS: GRAPH graph, OUT VERTEX_INDICES_LIST res, INTEGER min_size=0, INTEGER max_size=0 DEPS: res ON graph igraph_maximal_cliques_subset: PARAMS: |- - GRAPH graph, VERTEX_INDICES subset, PRIMARY OUT VERTEXSET_LIST res, + GRAPH graph, VERTEX_INDICES subset, PRIMARY OUT VERTEX_INDICES_LIST res, OUT INTEGER no, OUTFILE outfile=NULL, INTEGER min_size=0, INTEGER max_size=0 DEPS: subset ON graph, res ON graph @@ -1334,31 +1334,31 @@ igraph_clique_number: igraph_weighted_cliques: PARAMS: |- - GRAPH graph, VERTEXWEIGHTS vertex_weights=NULL, OUT VERTEXSET_LIST res, + GRAPH graph, VERTEX_WEIGHTS vertex_weights=NULL, OUT VERTEX_INDICES_LIST res, REAL min_weight=0, REAL max_weight=0, BOOLEAN maximal=False DEPS: vertex_weights ON graph, res ON graph igraph_largest_weighted_cliques: PARAMS: |- - GRAPH graph, VERTEXWEIGHTS vertex_weights=NULL, OUT VERTEXSET_LIST res + GRAPH graph, VERTEX_WEIGHTS vertex_weights=NULL, OUT VERTEX_INDICES_LIST res DEPS: vertex_weights ON graph, res ON graph igraph_weighted_clique_number: - PARAMS: GRAPH graph, VERTEXWEIGHTS vertex_weights=NULL, OUT REAL res + PARAMS: GRAPH graph, VERTEX_WEIGHTS vertex_weights=NULL, OUT REAL res DEPS: vertex_weights ON graph igraph_independent_vertex_sets: PARAMS: |- - GRAPH graph, OUT VERTEXSET_LIST res, INTEGER min_size=0, + GRAPH graph, OUT VERTEX_INDICES_LIST res, INTEGER min_size=0, INTEGER max_size=0 DEPS: res ON graph igraph_largest_independent_vertex_sets: - PARAMS: GRAPH graph, OUT VERTEXSET_LIST res + PARAMS: GRAPH graph, OUT VERTEX_INDICES_LIST res DEPS: res ON graph igraph_maximal_independent_vertex_sets: - PARAMS: GRAPH graph, OUT VERTEXSET_LIST res + PARAMS: GRAPH graph, OUT VERTEX_INDICES_LIST res DEPS: res ON graph igraph_independence_number: @@ -1392,7 +1392,7 @@ igraph_layout_fruchterman_reingold: GRAPH graph, INOUT MATRIX coords=NULL, BOOLEAN use_seed=False, INTEGER niter=500, REAL start_temp=sqrt(vcount(graph)), - LAYOUT_GRID grid=AUTO, EDGEWEIGHTS weights=NULL, + LAYOUT_GRID grid=AUTO, EDGE_WEIGHTS weights=NULL, OPTIONAL VECTOR minx, OPTIONAL VECTOR maxx, OPTIONAL VECTOR miny, OPTIONAL VECTOR maxy, DEPRECATED coolexp, DEPRECATED maxdelta, DEPRECATED area, @@ -1403,7 +1403,7 @@ igraph_layout_kamada_kawai: PARAMS: |- GRAPH graph, INOUT MATRIX coords, BOOLEAN use_seed=False, INTEGER maxiter=500, REAL epsilon=0.0, - REAL kkconst=vcount(graph), EDGEWEIGHTS weights=NULL, + REAL kkconst=vcount(graph), EDGE_WEIGHTS weights=NULL, OPTIONAL VECTOR minx, OPTIONAL VECTOR maxx, OPTIONAL VECTOR miny, OPTIONAL VECTOR maxy DEPS: weights ON graph @@ -1440,7 +1440,7 @@ igraph_layout_fruchterman_reingold_3d: GRAPH graph, INOUT MATRIX coords=NULL, BOOLEAN use_seed=False, INTEGER niter=500, REAL start_temp=sqrt(vcount(graph)), - EDGEWEIGHTS weights=NULL, + EDGE_WEIGHTS weights=NULL, OPTIONAL VECTOR minx, OPTIONAL VECTOR maxx, OPTIONAL VECTOR miny, OPTIONAL VECTOR maxy, OPTIONAL VECTOR minz, OPTIONAL VECTOR maxz, @@ -1452,7 +1452,7 @@ igraph_layout_kamada_kawai_3d: PARAMS: |- GRAPH graph, INOUT MATRIX coords, BOOLEAN use_seed=False, INTEGER maxiter=500, REAL epsilon=0.0, - REAL kkconst=vcount(graph), EDGEWEIGHTS weights=NULL, + REAL kkconst=vcount(graph), EDGE_WEIGHTS weights=NULL, OPTIONAL VECTOR minx, OPTIONAL VECTOR maxx, OPTIONAL VECTOR miny, OPTIONAL VECTOR maxy, OPTIONAL VECTOR minz, OPTIONAL VECTOR maxz @@ -1468,12 +1468,12 @@ igraph_layout_graphopt: igraph_layout_drl: PARAMS: |- GRAPH graph, INOUT MATRIX res, BOOLEAN use_seed=False, - DRL_OPTIONS options=drl_defaults$default, OPTIONAL EDGEWEIGHTS weights + DRL_OPTIONS options=drl_defaults$default, OPTIONAL EDGE_WEIGHTS weights igraph_layout_drl_3d: PARAMS: |- GRAPH graph, INOUT MATRIX res, BOOLEAN use_seed=False, - DRL_OPTIONS options=drl_defaults$default, OPTIONAL EDGEWEIGHTS weights + DRL_OPTIONS options=drl_defaults$default, OPTIONAL EDGE_WEIGHTS weights igraph_layout_merge_dla: PARAMS: GRAPH_PTR_LIST graphs, MATRIX_LIST coords, OUT MATRIX res @@ -1484,7 +1484,7 @@ igraph_layout_sugiyama: OPTIONAL OUT INDEX_VECTOR extd_to_orig_eids, OPTIONAL INDEX_VECTOR layers=NULL, REAL hgap=1, REAL vgap=1, INTEGER maxiter=100, - EDGEWEIGHTS weights=NULL + EDGE_WEIGHTS weights=NULL DEPS: weights ON graph igraph_layout_mds: @@ -1545,9 +1545,9 @@ igraph_bibcoupling: igraph_similarity_dice: PARAMS: |- - GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR vids=ALL, NEIMODE mode=ALL, + GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR vit_from=ALL, VERTEX_SELECTOR vit_to=ALL, NEIMODE mode=ALL, BOOLEAN loops=False - DEPS: vids ON graph + DEPS: vit_from ON graph, vit_to ON graph, res ON vit_from, res ON vit_to igraph_similarity_dice_es: PARAMS: |- @@ -1567,9 +1567,9 @@ igraph_similarity_inverse_log_weighted: igraph_similarity_jaccard: PARAMS: |- - GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR vids=ALL, NEIMODE mode=ALL, + GRAPH graph, OUT MATRIX res, VERTEX_SELECTOR vit_from=ALL, VERTEX_SELECTOR vit_to=ALL, NEIMODE mode=ALL, BOOLEAN loops=False - DEPS: vids ON graph res, mode ON vids + DEPS: vit_from ON graph, vit_to ON graph, res ON vit_from, res ON vit_to igraph_similarity_jaccard_es: PARAMS: |- @@ -1593,7 +1593,7 @@ igraph_compare_communities: igraph_community_spinglass: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, OUT REAL modularity, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT REAL modularity, OUT REAL temperature, OUT VECTOR_INT membership, OUT VECTOR_INT csize, INTEGER spins=25, BOOLEAN parupdate=False, REAL starttemp=1, REAL stoptemp=0.01, REAL coolfact=0.99, SPINCOMMUPDATE update_rule=CONFIG, REAL gamma=1.0, @@ -1602,15 +1602,15 @@ igraph_community_spinglass: igraph_community_spinglass_single: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, INTEGER vertex, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, INTEGER vertex, OUT VECTOR_INT community, OUT REAL cohesion, OUT REAL adhesion, - OUT INTEGER inner_links, OUT INTEGER outer_links, + OUT REAL inner_links, OUT REAL outer_links, INTEGER spins=25, SPINCOMMUPDATE update_rule=CONFIG, REAL gamma=1.0 DEPS: weights ON graph igraph_community_walktrap: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, INTEGER steps=4, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, INTEGER steps=4, OUT MATRIX_INT merges, OUT VECTOR modularity, OUT VECTOR_INT membership DEPS: weights ON graph @@ -1619,19 +1619,19 @@ igraph_community_edge_betweenness: GRAPH graph, OUT VECTOR_INT removed_edges, OPTIONAL OUT VECTOR edge_betweenness, OPTIONAL OUT MATRIX_INT merges, OPTIONAL OUT INDEX_VECTOR bridges, OPTIONAL OUT VECTOR modularity, OPTIONAL OUT VECTOR_INT membership, - BOOLEAN directed=True, OPTIONAL EDGEWEIGHTS weights=NULL + BOOLEAN directed=True, OPTIONAL EDGE_WEIGHTS weights=NULL DEPS: weights ON graph igraph_community_eb_get_merges: PARAMS: |- - GRAPH graph, BOOLEAN directed, EDGE_INDICES edges, OPTIONAL EDGEWEIGHTS weights, + GRAPH graph, BOOLEAN directed, EDGE_INDICES edges, OPTIONAL EDGE_WEIGHTS weights, OPTIONAL OUT MATRIX_INT merges, OPTIONAL OUT INDEX_VECTOR bridges, OPTIONAL OUT VECTOR modularity, OPTIONAL OUT VECTOR_INT membership DEPS: weights ON graph igraph_community_fastgreedy: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, OUT MATRIX_INT merges, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, OUT MATRIX_INT merges, OPTIONAL OUT VECTOR modularity, OPTIONAL OUT VECTOR_INT membership DEPS: weights ON graph @@ -1647,14 +1647,14 @@ igraph_le_community_to_membership: igraph_modularity: PARAMS: |- - GRAPH graph, VECTOR_INT membership, OPTIONAL EDGEWEIGHTS weights=NULL, + GRAPH graph, VECTOR_INT membership, OPTIONAL EDGE_WEIGHTS weights=NULL, REAL resolution=1.0, BOOLEAN directed=True, OUT REAL modularity DEPS: weights ON graph igraph_modularity_matrix: PARAMS: |- GRAPH graph, - OPTIONAL EDGEWEIGHTS weights, + OPTIONAL EDGE_WEIGHTS weights, REAL resolution=1.0, OUT MATRIX modmat, BOOLEAN directed=True @@ -1667,15 +1667,15 @@ igraph_reindex_membership: igraph_community_leading_eigenvector: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, + GRAPH graph, EDGE_WEIGHTS weights=NULL, OPTIONAL OUT MATRIX_INT merges, OPTIONAL OUT VECTOR_INT membership, INTEGER steps=-1, - INOUT ARPACKOPT options=ARPACK_DEFAULTS, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS, OPTIONAL OUT REAL modularity, BOOLEAN start=False, OPTIONAL OUT VECTOR eigenvalues, OPTIONAL OUT VECTOR_LIST eigenvectors, OPTIONAL OUT VECTOR history, - LEVCFUNC callback, EXTRA callback_extra + LEVC_FUNC callback, EXTRA callback_extra igraph_community_fluid_communities: PARAMS: |- @@ -1684,13 +1684,13 @@ igraph_community_fluid_communities: igraph_community_label_propagation: PARAMS: |- GRAPH graph, OUT VECTOR_INT membership, NEIMODE mode=ALL, - OPTIONAL EDGEWEIGHTS weights, OPTIONAL INDEX_VECTOR initial, + OPTIONAL EDGE_WEIGHTS weights, OPTIONAL INDEX_VECTOR initial, OPTIONAL VECTOR_BOOL fixed DEPS: weights ON graph igraph_community_multilevel: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, REAL resolution=1.0, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, REAL resolution=1.0, OUT VECTOR_INT membership, OPTIONAL OUT MATRIX_INT memberships, OPTIONAL OUT VECTOR modularity DEPS: weights ON graph @@ -1698,13 +1698,13 @@ igraph_community_multilevel: igraph_community_optimal_modularity: PARAMS: |- GRAPH graph, OUT REAL modularity, OPTIONAL OUT VECTOR_INT membership, - OPTIONAL EDGEWEIGHTS weights + OPTIONAL EDGE_WEIGHTS weights DEPS: weights ON graph igraph_community_leiden: PARAMS: |- - GRAPH graph, OPTIONAL EDGEWEIGHTS weights, - OPTIONAL VERTEXWEIGHTS vertex_weights, + GRAPH graph, OPTIONAL EDGE_WEIGHTS weights, + OPTIONAL VERTEX_WEIGHTS vertex_weights, REAL resolution, REAL beta=0.01, BOOLEAN start, INTEGER n_iterations=2, OPTIONAL INOUT VECTOR_INT membership, OUT INTEGER nb_clusters, OUT REAL quality @@ -1717,8 +1717,8 @@ igraph_split_join_distance: igraph_community_infomap: PARAMS: |- - GRAPH graph, EDGEWEIGHTS e_weights=NULL, - VERTEXWEIGHTS v_weights=NULL, INTEGER nb_trials=10, + GRAPH graph, EDGE_WEIGHTS e_weights=NULL, + VERTEX_WEIGHTS v_weights=NULL, INTEGER nb_trials=10, OUT VECTOR_INT membership, OUT REAL codelength DEPS: e_weights ON graph, v_weights ON graph @@ -1728,7 +1728,7 @@ igraph_community_voronoi: OPTIONAL OUT VECTOR_INT membership, OPTIONAL OUT VERTEX_INDICES generators, OPTIONAL OUT REAL modularity, - OPTIONAL EDGE_LENGTHS lengths, OPTIONAL EDGEWEIGHTS weights, + OPTIONAL EDGE_LENGTHS lengths, OPTIONAL EDGE_WEIGHTS weights, NEIMODE mode=OUT, REAL radius=-1 DEPS: generators ON graph, weights ON graph, lengths ON graph @@ -1738,20 +1738,20 @@ igraph_community_voronoi: igraph_graphlets: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, - OUT VERTEXSET_LIST cliques, OUT VECTOR Mu, INTEGER niter=1000 + GRAPH graph, EDGE_WEIGHTS weights=NULL, + OUT VERTEX_INDICES_LIST cliques, OUT VECTOR Mu, INTEGER niter=1000 DEPS: weights ON graph, cliques ON graph igraph_graphlets_candidate_basis: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, - OUT VERTEXSET_LIST cliques, OUT VECTOR thresholds + GRAPH graph, EDGE_WEIGHTS weights=NULL, + OUT VERTEX_INDICES_LIST cliques, OUT VECTOR thresholds DEPS: weights ON graph, cliques ON graph igraph_graphlets_project: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, - VERTEXSET_LIST cliques, INOUT VECTOR Muc, + GRAPH graph, EDGE_WEIGHTS weights=NULL, + VERTEX_INDICES_LIST cliques, INOUT VECTOR Muc, BOOLEAN startMu=False, INTEGER niter=1000 DEPS: weights ON graph @@ -1807,14 +1807,14 @@ igraph_from_hrg_dendrogram: igraph_get_adjacency: PARAMS: |- GRAPH graph, OUT MATRIX res, GETADJACENCY type=BOTH, - EDGEWEIGHTS weights=NULL, LOOPS loops=ONCE + EDGE_WEIGHTS weights=NULL, LOOPS loops=ONCE DEPS: weights ON graph igraph_get_adjacency_sparse: PARAMS: |- GRAPH graph, OUT SPARSEMAT sparsemat, GETADJACENCY type=BOTH, - EDGEWEIGHTS weights=NULL, LOOPS loops=ONCE + EDGE_WEIGHTS weights=NULL, LOOPS loops=ONCE DEPS: weights ON graph @@ -1824,14 +1824,14 @@ igraph_get_edgelist: igraph_get_stochastic: PARAMS: |- GRAPH graph, OUT MATRIX res, BOOLEAN column_wise=False, - EDGEWEIGHTS weights=NULL + EDGE_WEIGHTS weights=NULL DEPS: weights ON graph igraph_get_stochastic_sparse: PARAMS: |- GRAPH graph, OUT SPARSEMAT sparsemat, BOOLEAN column_wise=False, - EDGEWEIGHTS weights=NULL + EDGE_WEIGHTS weights=NULL DEPS: weights ON graph @@ -1942,50 +1942,50 @@ igraph_adjacent_triangles: igraph_local_scan_0: PARAMS: |- - GRAPH graph, OUT VECTOR res, EDGEWEIGHTS weights=NULL, + GRAPH graph, OUT VECTOR res, EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT DEPS: weights ON graph igraph_local_scan_0_them: PARAMS: |- GRAPH us, GRAPH them, OUT VECTOR res, - EDGEWEIGHTS weights_them=NULL, NEIMODE mode=OUT + EDGE_WEIGHTS weights_them=NULL, NEIMODE mode=OUT DEPS: weights_them ON them igraph_local_scan_1_ecount: PARAMS: |- - GRAPH graph, OUT VECTOR res, EDGEWEIGHTS weights=NULL, + GRAPH graph, OUT VECTOR res, EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT DEPS: weights ON graph igraph_local_scan_1_ecount_them: PARAMS: |- GRAPH us, GRAPH them, OUT VECTOR res, - EDGEWEIGHTS weights_them=NULL, NEIMODE mode=OUT + EDGE_WEIGHTS weights_them=NULL, NEIMODE mode=OUT DEPS: weights_them ON them igraph_local_scan_k_ecount: PARAMS: |- - GRAPH graph, INTEGER k, OUT VECTOR res, EDGEWEIGHTS weights=NULL, + GRAPH graph, INTEGER k, OUT VECTOR res, EDGE_WEIGHTS weights=NULL, NEIMODE mode=OUT DEPS: weights ON graph igraph_local_scan_k_ecount_them: PARAMS: |- GRAPH us, GRAPH them, INTEGER k, OUT VECTOR res, - EDGEWEIGHTS weights_them=NULL, NEIMODE mode=OUT + EDGE_WEIGHTS weights_them=NULL, NEIMODE mode=OUT DEPS: weights_them ON them igraph_local_scan_neighborhood_ecount: PARAMS: |- - GRAPH graph, OUT VECTOR res, EDGEWEIGHTS weights=NULL, - VERTEXSET_LIST neighborhoods + GRAPH graph, OUT VECTOR res, EDGE_WEIGHTS weights=NULL, + VERTEX_INDICES_LIST neighborhoods DEPS: weights ON graph igraph_local_scan_subset_ecount: PARAMS: |- - GRAPH graph, OUT VECTOR res, EDGEWEIGHTS weights=NULL, - VERTEXSET_LIST subsets + GRAPH graph, OUT VECTOR res, EDGE_WEIGHTS weights=NULL, + VERTEX_INDICES_LIST subsets DEPS: weights ON graph igraph_list_triangles: @@ -2046,7 +2046,7 @@ igraph_induced_subgraph_map: ####################################### igraph_gomory_hu_tree: - PARAMS: GRAPH graph, OUT GRAPH tree, OPTIONAL OUT VECTOR flows, OPTIONAL EDGE_CAPACITY capacity + PARAMS: GRAPH graph, OUT GRAPH tree, OPTIONAL OUT VECTOR flows, OPTIONAL EDGE_CAPACITIES capacity DEPS: capacity ON graph igraph_maxflow: @@ -2054,7 +2054,7 @@ igraph_maxflow: GRAPH graph, OUT REAL value, OPTIONAL OUT VECTOR flow, OUT EDGE_INDICES cut, OPTIONAL OUT VERTEX_INDICES partition1, OPTIONAL OUT VERTEX_INDICES partition2, VERTEX source, VERTEX target, - OPTIONAL EDGE_CAPACITY capacity, OPTIONAL OUT MAXFLOW_STATS stats + OPTIONAL EDGE_CAPACITIES capacity, OPTIONAL OUT MAXFLOW_STATS stats DEPS: |- capacity ON graph, source ON graph, target ON graph, partition1 ON graph, partition2 ON graph, flow ON graph, @@ -2063,30 +2063,30 @@ igraph_maxflow: igraph_maxflow_value: PARAMS: |- GRAPH graph, OUT REAL value, VERTEX source, VERTEX target, - OPTIONAL EDGE_CAPACITY capacity, OPTIONAL OUT MAXFLOW_STATS stats + OPTIONAL EDGE_CAPACITIES capacity, OPTIONAL OUT MAXFLOW_STATS stats DEPS: source ON graph, target ON graph, capacity ON graph igraph_mincut: PARAMS: |- GRAPH graph, OUT REAL value, OUT VERTEX_INDICES partition1, OUT VERTEX_INDICES partition2, OUT EDGE_INDICES cut, - OPTIONAL EDGE_CAPACITY capacity + OPTIONAL EDGE_CAPACITIES capacity DEPS: capacity ON graph, partition1 ON graph, partition2 ON graph, cut ON graph igraph_mincut_value: - PARAMS: GRAPH graph, OUT REAL res, OPTIONAL EDGE_CAPACITY capacity + PARAMS: GRAPH graph, OUT REAL res, OPTIONAL EDGE_CAPACITIES capacity DEPS: capacity ON graph igraph_residual_graph: PARAMS: |- - GRAPH graph, EDGE_CAPACITY capacity, OUT GRAPH residual, - OUT EDGE_CAPACITY residual_capacity, VECTOR flow + GRAPH graph, EDGE_CAPACITIES capacity, OUT GRAPH residual, + OUT EDGE_CAPACITIES residual_capacity, VECTOR flow DEPS: capacity ON graph, flow ON graph, residual_capacity ON residual igraph_reverse_residual_graph: PARAMS: |- - GRAPH graph, EDGE_CAPACITY capacity, OUT GRAPH residual, + GRAPH graph, EDGE_CAPACITIES capacity, OUT GRAPH residual, VECTOR flow DEPS: capacity ON graph, flow ON graph @@ -2095,7 +2095,7 @@ igraph_st_mincut: GRAPH graph, OUT REAL value, OUT EDGE_INDICES cut, OPTIONAL OUT VERTEX_INDICES partition1, OPTIONAL OUT VERTEX_INDICES partition2, - VERTEX source, VERTEX target, OPTIONAL EDGE_CAPACITY capacity + VERTEX source, VERTEX target, OPTIONAL EDGE_CAPACITIES capacity DEPS: |- capacity ON graph, source ON graph, target ON graph, partition1 ON graph, partition2 ON graph, cut ON graph @@ -2103,7 +2103,7 @@ igraph_st_mincut: igraph_st_mincut_value: PARAMS: |- GRAPH graph, OUT REAL res, VERTEX source, VERTEX target, - OPTIONAL EDGE_CAPACITY capacity + OPTIONAL EDGE_CAPACITIES capacity DEPS: source ON graph, target ON graph, capacity ON graph igraph_st_vertex_connectivity: @@ -2149,8 +2149,8 @@ igraph_dominator_tree: igraph_all_st_cuts: PARAMS: |- - GRAPH graph, OPTIONAL OUT EDGESET_LIST cuts, - OPTIONAL OUT VERTEXSET_LIST partition1s, + GRAPH graph, OPTIONAL OUT EDGE_INDICES_LIST cuts, + OPTIONAL OUT VERTEX_INDICES_LIST partition1s, VERTEX source, VERTEX target DEPS: |- source ON graph, target ON graph, cuts ON graph, @@ -2159,15 +2159,15 @@ igraph_all_st_cuts: igraph_all_st_mincuts: PARAMS: |- GRAPH graph, OUT REAL value, - OPTIONAL OUT EDGESET_LIST cuts, - OPTIONAL OUT VERTEXSET_LIST partition1s, - VERTEX source, VERTEX target, OPTIONAL EDGE_CAPACITY capacity + OPTIONAL OUT EDGE_INDICES_LIST cuts, + OPTIONAL OUT VERTEX_INDICES_LIST partition1s, + VERTEX source, VERTEX target, OPTIONAL EDGE_CAPACITIES capacity DEPS: |- capacity ON graph, source ON graph, target ON graph, cuts ON graph, partition1s ON graph igraph_even_tarjan_reduction: - PARAMS: GRAPH graph, OUT GRAPH graphbar, OPTIONAL OUT EDGE_CAPACITY capacity + PARAMS: GRAPH graph, OUT GRAPH graphbar, OPTIONAL OUT EDGE_CAPACITIES capacity DEPS: |- capacity ON graphbar @@ -2180,16 +2180,16 @@ igraph_is_minimal_separator: DEPS: candidate ON graph igraph_all_minimal_st_separators: - PARAMS: GRAPH graph, OUT VERTEXSET_LIST separators + PARAMS: GRAPH graph, OUT VERTEX_INDICES_LIST separators DEPS: separators ON graph igraph_minimum_size_separators: - PARAMS: GRAPH graph, OUT VERTEXSET_LIST separators + PARAMS: GRAPH graph, OUT VERTEX_INDICES_LIST separators DEPS: separators ON graph igraph_cohesive_blocks: PARAMS: |- - GRAPH graph, OUT VERTEXSET_LIST blocks, + GRAPH graph, OUT VERTEX_INDICES_LIST blocks, OUT VECTOR_INT cohesion, OUT INDEX_VECTOR parent, OUT GRAPH blockTree DEPS: blocks ON graph @@ -2211,6 +2211,16 @@ igraph_isoclass: igraph_isomorphic: PARAMS: GRAPH graph1, GRAPH graph2, OUT BOOLEAN iso +igraph_automorphism_group: + PARAMS: |- + GRAPH graph, OPTIONAL VERTEX_COLORS colors, OUT VERTEX_INDICES_LIST generators + DEPS: colors ON graph, generators ON graph + +igraph_count_automorphisms: + PARAMS: |- + GRAPH graph, OPTIONAL VERTEX_COLORS colors, OUT REAL result + DEPS: colors ON graph + igraph_isoclass_subgraph: PARAMS: GRAPH graph, VECTOR_INT vids, OUT INTEGER isoclass DEPS: vids ON graph @@ -2221,10 +2231,10 @@ igraph_isoclass_create: igraph_isomorphic_vf2: PARAMS: |- GRAPH graph1, GRAPH graph2, - OPTIONAL VERTEX_COLOR vertex_color1, - OPTIONAL VERTEX_COLOR vertex_color2, - OPTIONAL EDGE_COLOR edge_color1, - OPTIONAL EDGE_COLOR edge_color2, + OPTIONAL VERTEX_COLORS vertex_color1, + OPTIONAL VERTEX_COLORS vertex_color2, + OPTIONAL EDGE_COLORS edge_color1, + OPTIONAL EDGE_COLORS edge_color2, OUT BOOLEAN iso, OPTIONAL OUT INDEX_VECTOR map12, OPTIONAL OUT INDEX_VECTOR map21, OPTIONAL ISOCOMPAT_FUNC node_compat_fn, @@ -2237,8 +2247,8 @@ igraph_isomorphic_vf2: igraph_count_isomorphisms_vf2: PARAMS: |- GRAPH graph1, GRAPH graph2, - VERTEX_COLOR vertex_color1, VERTEX_COLOR vertex_color2, - EDGE_COLOR edge_color1, EDGE_COLOR edge_color2, + VERTEX_COLORS vertex_color1, VERTEX_COLORS vertex_color2, + EDGE_COLORS edge_color1, EDGE_COLORS edge_color2, OUT INTEGER count, ISOCOMPAT_FUNC node_compat_fn, ISOCOMPAT_FUNC edge_compat_fn, EXTRA extra DEPS: |- @@ -2248,8 +2258,8 @@ igraph_count_isomorphisms_vf2: igraph_get_isomorphisms_vf2: PARAMS: |- GRAPH graph1, GRAPH graph2, - VERTEX_COLOR vertex_color1, VERTEX_COLOR vertex_color2, - EDGE_COLOR edge_color1, EDGE_COLOR edge_color2, + VERTEX_COLORS vertex_color1, VERTEX_COLORS vertex_color2, + EDGE_COLORS edge_color1, EDGE_COLORS edge_color2, OUT VECTOR_INT_LIST maps, ISOCOMPAT_FUNC node_compat_fn, ISOCOMPAT_FUNC edge_compat_fn, EXTRA extra DEPS: |- @@ -2262,8 +2272,8 @@ igraph_subisomorphic: igraph_subisomorphic_vf2: PARAMS: |- GRAPH graph1, GRAPH graph2, - OPTIONAL VERTEX_COLOR vertex_color1, OPTIONAL VERTEX_COLOR vertex_color2, - OPTIONAL EDGE_COLOR edge_color1, OPTIONAL EDGE_COLOR edge_color2, + OPTIONAL VERTEX_COLORS vertex_color1, OPTIONAL VERTEX_COLORS vertex_color2, + OPTIONAL EDGE_COLORS edge_color1, OPTIONAL EDGE_COLORS edge_color2, OUT BOOLEAN iso, OPTIONAL OUT INDEX_VECTOR map12, OPTIONAL OUT INDEX_VECTOR map21, OPTIONAL ISOCOMPAT_FUNC node_compat_fn, OPTIONAL ISOCOMPAT_FUNC edge_compat_fn, @@ -2275,8 +2285,8 @@ igraph_subisomorphic_vf2: igraph_get_subisomorphisms_vf2_callback: PARAMS: |- GRAPH graph1, GRAPH graph2, - OPTIONAL VERTEX_COLOR vertex_color1, OPTIONAL VERTEX_COLOR vertex_color2, - OPTIONAL EDGE_COLOR edge_color1, OPTIONAL EDGE_COLOR edge_color2, + OPTIONAL VERTEX_COLORS vertex_color1, OPTIONAL VERTEX_COLORS vertex_color2, + OPTIONAL EDGE_COLORS edge_color1, OPTIONAL EDGE_COLORS edge_color2, OPTIONAL OUT INDEX_VECTOR map12, OPTIONAL OUT INDEX_VECTOR map21, ISOMORPHISM_FUNC ishohandler_fn, OPTIONAL ISOCOMPAT_FUNC node_compat_fn, OPTIONAL ISOCOMPAT_FUNC edge_compat_fn, EXTRA arg @@ -2287,8 +2297,8 @@ igraph_get_subisomorphisms_vf2_callback: igraph_count_subisomorphisms_vf2: PARAMS: |- GRAPH graph1, GRAPH graph2, - VERTEX_COLOR vertex_color1, VERTEX_COLOR vertex_color2, - EDGE_COLOR edge_color1, EDGE_COLOR edge_color2, + VERTEX_COLORS vertex_color1, VERTEX_COLORS vertex_color2, + EDGE_COLORS edge_color1, EDGE_COLORS edge_color2, OUT INTEGER count, ISOCOMPAT_FUNC node_compat_fn, ISOCOMPAT_FUNC edge_compat_fn, EXTRA extra DEPS: |- @@ -2298,8 +2308,8 @@ igraph_count_subisomorphisms_vf2: igraph_get_subisomorphisms_vf2: PARAMS: |- GRAPH graph1, GRAPH graph2, - VERTEX_COLOR vertex_color1, VERTEX_COLOR vertex_color2, - EDGE_COLOR edge_color1, EDGE_COLOR edge_color2, + VERTEX_COLORS vertex_color1, VERTEX_COLORS vertex_color2, + EDGE_COLORS edge_color1, EDGE_COLORS edge_color2, OUT VECTOR_INT_LIST maps, ISOCOMPAT_FUNC node_compat_fn, ISOCOMPAT_FUNC edge_compat_fn, EXTRA extra DEPS: |- @@ -2308,7 +2318,13 @@ igraph_get_subisomorphisms_vf2: igraph_canonical_permutation: PARAMS: |- - GRAPH graph, OPTIONAL VERTEX_COLOR colors, + GRAPH graph, OPTIONAL VERTEX_COLORS colors, + OUT INDEX_VECTOR labeling + DEPS: colors ON graph + +igraph_canonical_permutation_bliss: + PARAMS: |- + GRAPH graph, OPTIONAL VERTEX_COLORS colors, OUT INDEX_VECTOR labeling, BLISSSH sh="fm", OUT BLISSINFO info DEPS: colors ON graph @@ -2318,26 +2334,26 @@ igraph_permute_vertices: igraph_isomorphic_bliss: PARAMS: |- GRAPH graph1, GRAPH graph2, - OPTIONAL VERTEX_COLOR colors1, OPTIONAL VERTEX_COLOR colors2, + OPTIONAL VERTEX_COLORS colors1, OPTIONAL VERTEX_COLORS colors2, OUT BOOLEAN iso, OPTIONAL OUT INDEX_VECTOR map12, OPTIONAL OUT INDEX_VECTOR map21, BLISSSH sh="fm", OPTIONAL OUT BLISSINFO info1, OPTIONAL OUT BLISSINFO info2 DEPS: colors1 ON graph1, colors2 ON graph2 -igraph_count_automorphisms: +igraph_count_automorphisms_bliss: PARAMS: |- - GRAPH graph, OPTIONAL VERTEX_COLOR colors, BLISSSH sh="fm", OUT BLISSINFO info + GRAPH graph, OPTIONAL VERTEX_COLORS colors, BLISSSH sh="fm", OUT BLISSINFO info DEPS: colors ON graph -igraph_automorphism_group: +igraph_automorphism_group_bliss: PARAMS: |- - GRAPH graph, OPTIONAL VERTEX_COLOR colors, PRIMARY OUT VERTEXSET_LIST generators, + GRAPH graph, OPTIONAL VERTEX_COLORS colors, PRIMARY OUT VERTEX_INDICES_LIST generators, BLISSSH sh="fm", OUT BLISSINFO info DEPS: colors ON graph, generators ON graph igraph_subisomorphic_lad: PARAMS: |- - GRAPH pattern, GRAPH target, OPTIONAL VERTEXSET_LIST domains, + GRAPH pattern, GRAPH target, OPTIONAL VERTEX_INDICES_LIST domains, OPTIONAL OUT BOOLEAN iso, OUT INDEX_VECTOR map, OPTIONAL OUT VECTOR_INT_LIST maps, BOOLEAN induced, INTEGER time_limit @@ -2373,7 +2389,7 @@ igraph_maximum_bipartite_matching: OPTIONAL OUT INTEGER matching_size, OPTIONAL OUT REAL matching_weight, OUT INDEX_VECTOR matching, - OPTIONAL EDGEWEIGHTS weights, REAL eps=.Machine$double.eps + OPTIONAL EDGE_WEIGHTS weights, REAL eps=.Machine$double.eps DEPS: types ON graph, weights ON graph ####################################### @@ -2382,20 +2398,20 @@ igraph_maximum_bipartite_matching: igraph_adjacency_spectral_embedding: PARAMS: |- - GRAPH graph, INTEGER no, EDGEWEIGHTS weights=NULL, + GRAPH graph, INTEGER no, EDGE_WEIGHTS weights=NULL, EIGENWHICHPOS which=ASE, BOOLEAN scaled=True, OUT MATRIX X, OPTIONAL OUT MATRIX Y, OPTIONAL OUT VECTOR D, VECTOR cvec=AsmDefaultCvec, - INOUT ARPACKOPT options=ARPACK_DEFAULTS + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS DEPS: weights ON graph, cvec ON graph igraph_laplacian_spectral_embedding: PARAMS: |- - GRAPH graph, INTEGER no, EDGEWEIGHTS weights=NULL, + GRAPH graph, INTEGER no, EDGE_WEIGHTS weights=NULL, EIGENWHICHPOS which=ASE, LSETYPE type=Default, BOOLEAN scaled=True, OUT MATRIX X, OPTIONAL OUT MATRIX Y, OPTIONAL OUT VECTOR D, - INOUT ARPACKOPT options=ARPACK_DEFAULTS + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS DEPS: weights ON graph, type ON graph ####################################### @@ -2406,8 +2422,8 @@ igraph_eigen_adjacency: PARAMS: |- GRAPH graph, EIGENALGO algorithm=ARPACK, EIGENWHICH which=Default, - INOUT ARPACKOPT options=ARPACK_DEFAULTS, - INOUT ARPACKSTORAGE storage, OUT VECTOR values, OUT MATRIX vectors, + INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS, + INOUT ARPACK_STORAGE storage, OUT VECTOR values, OUT MATRIX vectors, OUT VECTOR_COMPLEX cmplxvalues, OUT MATRIX_COMPLEX cmplxvectors ####################################### @@ -2454,15 +2470,15 @@ igraph_cmp_epsilon: igraph_eigen_matrix: PARAMS: |- - MATRIX A, SPARSEMAT sA, ARPACKFUNC fun, INT n, EXTRA extra, - EIGENALGO algorithm, EIGENWHICH which, INOUT ARPACKOPT options=ARPACK_DEFAULTS, - INOUT ARPACKSTORAGE storage, OUT VECTOR_COMPLEX values, OUT MATRIX_COMPLEX vectors + MATRIX A, SPARSEMAT sA, ARPACK_FUNC fun, INT n, EXTRA extra, + EIGENALGO algorithm, EIGENWHICH which, INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS, + INOUT ARPACK_STORAGE storage, OUT VECTOR_COMPLEX values, OUT MATRIX_COMPLEX vectors igraph_eigen_matrix_symmetric: PARAMS: |- - MATRIX A, SPARSEMAT sA, ARPACKFUNC fun, INT n, EXTRA extra, - EIGENALGO algorithm, EIGENWHICH which, INOUT ARPACKOPT options=ARPACK_DEFAULTS, - INOUT ARPACKSTORAGE storage, OUT VECTOR values, OUT MATRIX vectors + MATRIX A, SPARSEMAT sA, ARPACK_FUNC fun, INT n, EXTRA extra, + EIGENALGO algorithm, EIGENWHICH which, INOUT ARPACK_OPTIONS options=ARPACK_DEFAULTS, + INOUT ARPACK_STORAGE storage, OUT VECTOR values, OUT MATRIX vectors igraph_solve_lsap: PARAMS: MATRIX c, INTEGER n, OUT VECTOR_INT p @@ -2487,11 +2503,11 @@ igraph_eulerian_cycle: ####################################### igraph_fundamental_cycles: - PARAMS: GRAPH graph, OUT EDGESET_LIST basis, OPTIONAL VERTEX start, INTEGER bfs_cutoff, EDGEWEIGHTS weights=NULL + PARAMS: GRAPH graph, OUT EDGE_INDICES_LIST basis, OPTIONAL VERTEX start, INTEGER bfs_cutoff, EDGE_WEIGHTS weights=NULL DEPS: weights ON graph, basis ON graph, start ON graph igraph_minimum_cycle_basis: - PARAMS: GRAPH graph, OUT EDGESET_LIST basis, INTEGER bfs_cutoff, BOOLEAN complete, BOOLEAN use_cycle_order, EDGEWEIGHTS weights=NULL + PARAMS: GRAPH graph, OUT EDGE_INDICES_LIST basis, INTEGER bfs_cutoff, BOOLEAN complete, BOOLEAN use_cycle_order, EDGE_WEIGHTS weights=NULL DEPS: weights ON graph, basis ON graph ####################################### @@ -2519,14 +2535,14 @@ igraph_is_complete: PARAMS: GRAPH graph, OUT BOOLEAN res igraph_minimum_spanning_tree: - PARAMS: GRAPH graph, OUT EDGE_INDICES res, EDGEWEIGHTS weights=NULL + PARAMS: GRAPH graph, OUT EDGE_INDICES res, EDGE_WEIGHTS weights=NULL DEPS: res ON graph, weights ON graph igraph_minimum_spanning_tree_unweighted: PARAMS: GRAPH graph, OUT GRAPH mst igraph_minimum_spanning_tree_prim: - PARAMS: GRAPH graph, OUT GRAPH mst, EDGEWEIGHTS weights + PARAMS: GRAPH graph, OUT GRAPH mst, EDGE_WEIGHTS weights DEPS: weights ON graph igraph_random_spanning_tree: @@ -2541,7 +2557,7 @@ igraph_tree_game: ####################################### igraph_vertex_coloring_greedy: - PARAMS: GRAPH graph, OUT VERTEX_COLOR colors, GREEDY_COLORING_HEURISTIC heuristic=NEIGHBORS + PARAMS: GRAPH graph, OUT VERTEX_COLORS colors, GREEDY_COLORING_HEURISTIC heuristic=NEIGHBORS DEPS: colors ON graph ####################################### @@ -2550,25 +2566,25 @@ igraph_vertex_coloring_greedy: igraph_deterministic_optimal_imitation: PARAMS: |- - GRAPH graph, VERTEX vid, OPTIMALITY optimality=MAXIMUM, VERTEX_QTY quantities, + GRAPH graph, VERTEX vid, OPTIMALITY optimality=MAXIMUM, VERTEX_QTYS quantities, INOUT VECTOR_INT strategies, NEIMODE mode=OUT DEPS: vid ON graph, quantities ON graph, strategies ON graph igraph_moran_process: PARAMS: |- - GRAPH graph, EDGEWEIGHTS weights=NULL, INOUT VERTEX_QTY quantities, + GRAPH graph, EDGE_WEIGHTS weights=NULL, INOUT VERTEX_QTYS quantities, INOUT VECTOR_INT strategies, NEIMODE mode=OUT DEPS: weights ON graph, quantities ON graph, strategies ON graph igraph_roulette_wheel_imitation: PARAMS: |- - GRAPH graph, VERTEX vid, BOOLEAN is_local, VERTEX_QTY quantities, + GRAPH graph, VERTEX vid, BOOLEAN is_local, VERTEX_QTYS quantities, INOUT VECTOR_INT strategies, NEIMODE mode=OUT DEPS: vid ON graph, quantities ON graph, strategies ON graph igraph_stochastic_imitation: PARAMS: |- - GRAPH graph, VERTEX vid, IMITATE_ALGORITHM algo, VERTEX_QTY quantities, + GRAPH graph, VERTEX vid, IMITATE_ALGORITHM algo, VERTEX_QTYS quantities, INOUT VECTOR_INT strategies, NEIMODE mode=OUT DEPS: vid ON graph, quantities ON graph, strategies ON graph diff --git a/src/vendor/cigraph/interfaces/types.yaml b/src/vendor/cigraph/interfaces/types.yaml index 9799d02652d..c35461ad169 100644 --- a/src/vendor/cigraph/interfaces/types.yaml +++ b/src/vendor/cigraph/interfaces/types.yaml @@ -177,12 +177,12 @@ BIPARTITE_TYPES: CTYPE: igraph_vector_bool_t FLAGS: BY_REF -EDGE_CAPACITY: +EDGE_CAPACITIES: # A vector containing edge capacities (typically for max-flow algorithms) CTYPE: igraph_vector_t FLAGS: BY_REF -EDGE_COLOR: +EDGE_COLORS: # A vector containing edge colors CTYPE: igraph_vector_int_t FLAGS: BY_REF @@ -192,12 +192,12 @@ EDGE_LENGTHS: CTYPE: igraph_vector_t FLAGS: BY_REF -EDGEWEIGHTS: +EDGE_WEIGHTS: # A vector containing edge weights CTYPE: igraph_vector_t FLAGS: BY_REF -EDGESET_LIST: +EDGE_INDICES_LIST: # A list containing vectors of igraph integers where each such # vector represents a sequence of edge indices. CTYPE: igraph_vector_int_list_t @@ -213,7 +213,7 @@ GRAPH_PTR_LIST: CTYPE: igraph_vector_ptr_t FLAGS: BY_REF -VERTEX_QTY: +VERTEX_QTYS: # A vector of floating-point numbers where each entry corresponds to # one of the vertices in a graph and its value represents some quantity # associated to the vertex with the same index. Higher-level interfaces may @@ -227,18 +227,18 @@ SIR_LIST: CTYPE: igraph_vector_ptr_t FLAGS: BY_REF -VERTEXSET_LIST: +VERTEX_INDICES_LIST: # A list containing vectors of igraph integers where each such # vector represents a sequence of vertex indices. CTYPE: igraph_vector_int_list_t FLAGS: BY_REF -VERTEX_COLOR: +VERTEX_COLORS: # A vector containing vertex colors CTYPE: igraph_vector_int_t FLAGS: BY_REF -VERTEXWEIGHTS: +VERTEX_WEIGHTS: # A vector containing vertex weights CTYPE: igraph_vector_t FLAGS: BY_REF @@ -511,7 +511,7 @@ WRITE_GML_SW: # Callbacks ############################################################################### -ARPACKFUNC: +ARPACK_FUNC: # ARPACK matrix multiplication function. CTYPE: igraph_arpack_function_t @@ -540,7 +540,7 @@ ISOMORPHISM_FUNC: # isomorphism is found CTYPE: igraph_isohandler_t -LEVCFUNC: +LEVC_FUNC: # Callback function for igraph_leading_eigenvector_community(). Called # after each eigenvalue / eigenvector calculation. CTYPE: igraph_community_leading_eigenvector_callback_t @@ -549,12 +549,12 @@ LEVCFUNC: # Miscellaneous ############################################################################### -ARPACKOPT: +ARPACK_OPTIONS: # Structure that contains the options of the ARPACK eigensolver. CTYPE: igraph_arpack_options_t FLAGS: BY_REF -ARPACKSTORAGE: +ARPACK_STORAGE: # Pointer to a general-purpose memory block that ARPACK-based algorithms # may use as a working area. CTYPE: igraph_arpack_storage_t @@ -565,10 +565,9 @@ ASTAR_HEURISTIC_FUNC: CTYPE: igraph_astar_heuristic_func_t ATTRIBUTES: - # An opaque data structure that a high-level interface may use to pass - # information about graph/vertex/edge attributes to a low-level igraph - # C function - CTYPE: void + # A data structure specifying graph/vertex/edge attributes to add to a + # graph in a low-level igraph C function + CTYPE: igraph_attribute_record_list_t FLAGS: BY_REF BLISSINFO: diff --git a/src/vendor/cigraph/src/centrality/betweenness.c b/src/vendor/cigraph/src/centrality/betweenness.c index 9adff201e2b..bed0d23a8e7 100644 --- a/src/vendor/cigraph/src/centrality/betweenness.c +++ b/src/vendor/cigraph/src/centrality/betweenness.c @@ -472,10 +472,8 @@ static igraph_error_t igraph_i_betweenness_check_weights( * calculating weighted betweenness. No edge weight may be NaN. * Supply a null pointer here for unweighted betweenness. * \return Error code: - * \c IGRAPH_ENOMEM, not enough memory for - * temporary data. - * \c IGRAPH_EINVVID, invalid vertex ID passed in - * \p vids. + * \c IGRAPH_ENOMEM, not enough memory for temporary data. + * \c IGRAPH_EINVVID, invalid vertex ID passed in \p vids. * * Time complexity: O(|V||E|), * |V| and @@ -518,10 +516,8 @@ igraph_error_t igraph_betweenness(const igraph_t *graph, igraph_vector_t *res, * If negative, the exact betweenness will be calculated, and * there will be no upper limit on path lengths. * \return Error code: - * \c IGRAPH_ENOMEM, not enough memory for - * temporary data. - * \c IGRAPH_EINVVID, invalid vertex ID passed in - * \p vids. + * \c IGRAPH_ENOMEM, not enough memory for temporary data. + * \c IGRAPH_EINVVID, invalid vertex ID passed in \p vids. * * Time complexity: O(|V||E|), * |V| and diff --git a/src/vendor/cigraph/src/community/edge_betweenness.c b/src/vendor/cigraph/src/community/edge_betweenness.c index 16b64f186fa..af0a3d3adaa 100644 --- a/src/vendor/cigraph/src/community/edge_betweenness.c +++ b/src/vendor/cigraph/src/community/edge_betweenness.c @@ -234,7 +234,10 @@ igraph_error_t igraph_community_eb_get_merges(const igraph_t *graph, igraph_integer_t max_merges; if (! igraph_vector_int_isininterval(edges, 0, no_of_edges-1)) { - IGRAPH_ERROR("Invalid edge ID.", IGRAPH_EINVAL); + IGRAPH_ERROR( + "Cannot calculate merges of edge betweenness community detection.", + IGRAPH_EINVEID + ); } if (no_removed_edges < no_of_edges) { IGRAPH_ERRORF("Number of removed edges (%" IGRAPH_PRId ") should be equal to " diff --git a/src/vendor/cigraph/src/community/fluid.c b/src/vendor/cigraph/src/community/fluid.c index d419f7ac12f..593f0d3f0c6 100644 --- a/src/vendor/cigraph/src/community/fluid.c +++ b/src/vendor/cigraph/src/community/fluid.c @@ -132,7 +132,7 @@ igraph_error_t igraph_community_fluid_communities(const igraph_t *graph, igraph_vector_fill(&density, max_density); /* Initialize com_to_numvertices and initialize communities into membership vector */ - IGRAPH_CHECK(igraph_vector_int_shuffle(&node_order)); + igraph_vector_int_shuffle(&node_order); for (i = 0; i < no_of_communities; i++) { /* Initialize membership at initial nodes for each community * where 0 refers to have no label*/ @@ -165,7 +165,7 @@ igraph_error_t igraph_community_fluid_communities(const igraph_t *graph, running = false; /* Shuffle the node ordering vector */ - IGRAPH_CHECK(igraph_vector_int_shuffle(&node_order)); + igraph_vector_int_shuffle(&node_order); /* In the prescribed order, loop over the vertices and reassign labels */ for (i = 0; i < no_of_nodes; i++) { /* Clear dominant_labels and nonzero_labels vectors */ diff --git a/src/vendor/cigraph/src/community/label_propagation.c b/src/vendor/cigraph/src/community/label_propagation.c index 09a9eb743a7..07b38934391 100644 --- a/src/vendor/cigraph/src/community/label_propagation.c +++ b/src/vendor/cigraph/src/community/label_propagation.c @@ -272,7 +272,7 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, running = false; } else { /* Shuffle the node ordering vector if we are in the label updating iteration */ - IGRAPH_CHECK(igraph_vector_int_shuffle(&node_order)); + igraph_vector_int_shuffle(&node_order); } RNG_BEGIN(); @@ -403,7 +403,7 @@ igraph_error_t igraph_community_label_propagation(const igraph_t *graph, /* In the directed case, the outcome depends on the node ordering, thus we * shuffle nodes one more time. */ - IGRAPH_CHECK(igraph_vector_int_shuffle(&node_order)); + igraph_vector_int_shuffle(&node_order); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); diff --git a/src/vendor/cigraph/src/community/leading_eigenvector.c b/src/vendor/cigraph/src/community/leading_eigenvector.c index 91b88c4fbfd..b351e35b7f7 100644 --- a/src/vendor/cigraph/src/community/leading_eigenvector.c +++ b/src/vendor/cigraph/src/community/leading_eigenvector.c @@ -546,7 +546,7 @@ igraph_error_t igraph_community_leading_eigenvector( } RNG_END(); igraph_vector_view(&start_vec, storage.resid, options->n); - IGRAPH_CHECK(igraph_vector_shuffle(&start_vec)); + igraph_vector_shuffle(&start_vec); { igraph_error_t retval; diff --git a/src/vendor/cigraph/src/community/leiden.c b/src/vendor/cigraph/src/community/leiden.c index e9aa9ada241..122bd0cd459 100644 --- a/src/vendor/cigraph/src/community/leiden.c +++ b/src/vendor/cigraph/src/community/leiden.c @@ -80,7 +80,7 @@ static igraph_error_t igraph_i_community_leiden_fastmovenodes( /* Shuffle nodes */ IGRAPH_CHECK(igraph_vector_int_init_range(&node_order, 0, n)); IGRAPH_FINALLY(igraph_vector_int_destroy, &node_order); - IGRAPH_CHECK(igraph_vector_int_shuffle(&node_order)); + igraph_vector_int_shuffle(&node_order); /* Add to the queue */ for (i = 0; i < n; i++) { @@ -339,7 +339,7 @@ static igraph_error_t igraph_i_community_leiden_mergenodes( /* Shuffle nodes */ IGRAPH_CHECK(igraph_vector_int_init_copy(&node_order, node_subset)); IGRAPH_FINALLY(igraph_vector_int_destroy, &node_order); - IGRAPH_CHECK(igraph_vector_int_shuffle(&node_order)); + igraph_vector_int_shuffle(&node_order); /* Initialize non singleton clusters */ IGRAPH_VECTOR_BOOL_INIT_FINALLY(&non_singleton_cluster, n); diff --git a/src/vendor/cigraph/src/community/spinglass/clustertool.cpp b/src/vendor/cigraph/src/community/spinglass/clustertool.cpp index 537a0df6f39..f423ce2e87c 100644 --- a/src/vendor/cigraph/src/community/spinglass/clustertool.cpp +++ b/src/vendor/cigraph/src/community/spinglass/clustertool.cpp @@ -389,10 +389,11 @@ static igraph_error_t igraph_i_community_spinglass_orig( * \param adhesion Pointer to a real variable, if not \c NULL the * adhesion index of the community will be stored here. * \param inner_links Pointer to an integer, if not \c NULL the - * number of edges within the community is stored here. + * number of edges within the community (or the sum of their weights) + * is stored here. * \param outer_links Pointer to an integer, if not \c NULL the * number of edges between the community and the rest of the graph - * will be stored here. + * (or the sum of their weights) will be stored here. * \param spins The number of spins to use, this can be higher than * the actual number of clusters in the network, in which case some * clusters will contain zero vertices. @@ -427,8 +428,8 @@ igraph_error_t igraph_community_spinglass_single(const igraph_t *graph, igraph_vector_int_t *community, igraph_real_t *cohesion, igraph_real_t *adhesion, - igraph_integer_t *inner_links, - igraph_integer_t *outer_links, + igraph_real_t *inner_links, + igraph_real_t *outer_links, igraph_integer_t spins, igraph_spincomm_update_t update_rule, igraph_real_t gamma) { diff --git a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp index f454154e4dd..2e29f4f510c 100644 --- a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp +++ b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.cpp @@ -773,8 +773,8 @@ double PottsModel::FindCommunityFromStart( igraph_vector_int_t *result, igraph_real_t *cohesion, igraph_real_t *adhesion, - igraph_integer_t *my_inner_links, - igraph_integer_t *my_outer_links) const { + igraph_real_t *my_inner_links, + igraph_real_t *my_outer_links) const { DLList_Iter iter, iter2; DLList_Iter l_iter; DLList to_do; diff --git a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.h b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.h index 1cecba4268c..6e96ea6c6de 100644 --- a/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.h +++ b/src/vendor/cigraph/src/community/spinglass/pottsmodel_2.h @@ -110,8 +110,8 @@ class PottsModel { igraph_vector_int_t *result, igraph_real_t *cohesion, igraph_real_t *adhesion, - igraph_integer_t *inner_links, - igraph_integer_t *outer_links) const; + igraph_real_t *inner_links, + igraph_real_t *outer_links) const; }; diff --git a/src/vendor/cigraph/src/connectivity/components.c b/src/vendor/cigraph/src/connectivity/components.c index d049883335b..70a6b3f0a55 100644 --- a/src/vendor/cigraph/src/connectivity/components.c +++ b/src/vendor/cigraph/src/connectivity/components.c @@ -565,34 +565,6 @@ static igraph_error_t igraph_i_is_connected_weak(const igraph_t *graph, igraph_b return IGRAPH_SUCCESS; } -/** - * \function igraph_decompose_destroy - * \brief Frees the contents of a pointer vector holding graphs. - * - * This function destroys and frees all igraph_t - * objects held in \p complist. However, it does not destroy - * \p complist itself. Use \ref igraph_vector_ptr_destroy() to destroy - * \p complist. - * - * \param complist The list of graphs to destroy. - * - * Time complexity: O(n), n is the number of items. - * - * \deprecated 0.10.0 - */ - -void igraph_decompose_destroy(igraph_vector_ptr_t *complist) { - igraph_integer_t i, n; - - n = igraph_vector_ptr_size(complist); - for (i = 0; i < n; i++) { - if (VECTOR(*complist)[i] != 0) { - igraph_destroy(VECTOR(*complist)[i]); - IGRAPH_FREE(VECTOR(*complist)[i]); - } - } -} - static igraph_error_t igraph_i_decompose_weak(const igraph_t *graph, igraph_graph_list_t *components, igraph_integer_t maxcompno, igraph_integer_t minelements); @@ -677,6 +649,7 @@ static igraph_error_t igraph_i_decompose_weak(const igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&verts, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&neis, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&vids_old2new, no_of_nodes); + igraph_vector_int_fill(&vids_old2new, -1); /* vids_old2new would have been created internally in igraph_induced_subgraph(), but it is slow if the graph is large and consists of many small components, @@ -784,6 +757,8 @@ static igraph_error_t igraph_i_decompose_strong(const igraph_t *graph, /* The result */ IGRAPH_VECTOR_INT_INIT_FINALLY(&vids_old2new, no_of_nodes); + igraph_vector_int_fill(&vids_old2new, -1); + IGRAPH_VECTOR_INT_INIT_FINALLY(&verts, 0); IGRAPH_VECTOR_INT_INIT_FINALLY(&next_nei, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&out, 0); @@ -1257,8 +1232,6 @@ igraph_error_t igraph_biconnected_components(const igraph_t *graph, * \function igraph_is_biconnected * \brief Checks whether a graph is biconnected. * - * \experimental - * * A graph is biconnected if the removal of any single vertex (and * its incident edges) does not disconnect it. * diff --git a/src/vendor/cigraph/src/constructors/adjacency.c b/src/vendor/cigraph/src/constructors/adjacency.c index 459403da24d..28e4a04c7f3 100644 --- a/src/vendor/cigraph/src/constructors/adjacency.c +++ b/src/vendor/cigraph/src/constructors/adjacency.c @@ -303,9 +303,9 @@ static igraph_error_t igraph_i_adjacency_min( * will return an error code. * \endclist * \return Error code, - * \c IGRAPH_NONSQUARE: non-square matrix. - * \c IGRAPH_EINVAL: Negative entry was found in adjacency matrix, or an - * odd number was found in the diagonal with \c IGRAPH_LOOPS_TWICE + * \c IGRAPH_EINVAL: Non-square adjacency matrix, negative entry in + * adjacency matrix, or an odd number was found in the diagonal with + * \c IGRAPH_LOOPS_TWICE * * Time complexity: O(|V||V|), * |V| is the number of vertices in the graph. @@ -322,7 +322,7 @@ igraph_error_t igraph_adjacency( /* Some checks */ if (igraph_matrix_nrow(adjmatrix) != igraph_matrix_ncol(adjmatrix)) { - IGRAPH_ERROR("Adjacency matrix is non-square.", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Adjacency matrix is non-square.", IGRAPH_EINVAL); } if (no_of_nodes != 0 && igraph_matrix_min(adjmatrix) < 0) { @@ -720,7 +720,7 @@ static igraph_error_t igraph_i_weighted_adjacency_min( * incident on the corresponding vertex. * \endclist * \return Error code, - * \c IGRAPH_NONSQUARE: non-square matrix. + * \c IGRAPH_EINVAL: non-square matrix. * * Time complexity: O(|V||V|), * |V| is the number of vertices in the graph. @@ -737,7 +737,7 @@ igraph_error_t igraph_weighted_adjacency( /* Some checks */ if (igraph_matrix_nrow(adjmatrix) != igraph_matrix_ncol(adjmatrix)) { - IGRAPH_ERROR("Non-square matrix", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Non-square matrix", IGRAPH_EINVAL); } IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); @@ -1070,7 +1070,7 @@ igraph_error_t igraph_sparse_adjacency(igraph_t *graph, igraph_sparsemat_t *adjm "form.", IGRAPH_EINVAL); } if (no_of_nodes != igraph_sparsemat_ncol(adjmatrix)) { - IGRAPH_ERROR("Adjacency matrix is non-square.", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Adjacency matrix is non-square.", IGRAPH_EINVAL); } if (no_of_nodes != 0 && igraph_sparsemat_min(adjmatrix) < 0) { @@ -1366,7 +1366,7 @@ igraph_error_t igraph_sparse_weighted_adjacency( IGRAPH_ERROR("Sparse adjacency matrix should be in column-compressed form.", IGRAPH_EINVAL); } if (no_of_nodes != igraph_sparsemat_ncol(adjmatrix)) { - IGRAPH_ERROR("Adjacency matrix is non-square.", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Adjacency matrix is non-square.", IGRAPH_EINVAL); } IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); diff --git a/src/vendor/cigraph/src/constructors/basic_constructors.c b/src/vendor/cigraph/src/constructors/basic_constructors.c index 892c3cda350..1badfd933a2 100644 --- a/src/vendor/cigraph/src/constructors/basic_constructors.c +++ b/src/vendor/cigraph/src/constructors/basic_constructors.c @@ -51,10 +51,8 @@ * not. If yes, then the first edge points from the first * vertex ID in \p edges to the second, etc. * \return Error code: - * \c IGRAPH_EINVEVECTOR: invalid edges - * vector (odd number of vertices). - * \c IGRAPH_EINVVID: invalid (negative) - * vertex ID. + * \c IGRAPH_EINVAL: invalid edges vector (odd number of vertices). + * \c IGRAPH_EINVVID: invalid (negative) vertex ID. * * Time complexity: O(|V|+|E|), * |V| is the number of vertices, @@ -69,9 +67,9 @@ igraph_error_t igraph_create(igraph_t *graph, const igraph_vector_int_t *edges, igraph_integer_t max; if (igraph_vector_int_size(edges) % 2 != 0) { - IGRAPH_ERROR("Invalid (odd) edges vector.", IGRAPH_EINVEVECTOR); + IGRAPH_ERROR("Invalid (odd) edges vector.", IGRAPH_EINVAL); } - if (has_edges && !igraph_vector_int_isininterval(edges, 0, IGRAPH_VCOUNT_MAX-1)) { + if (!igraph_vector_int_isininterval(edges, 0, IGRAPH_VCOUNT_MAX-1)) { IGRAPH_ERROR("Invalid (negative or too large) vertex ID.", IGRAPH_EINVVID); } diff --git a/src/vendor/cigraph/src/core/error.c b/src/vendor/cigraph/src/core/error.c index 6e928cc00f2..10bd621ed37 100644 --- a/src/vendor/cigraph/src/core/error.c +++ b/src/vendor/cigraph/src/core/error.c @@ -91,9 +91,9 @@ static const char *igraph_i_error_strings[] = { /* 3 */ "Parse error", /* 4 */ "Invalid value", /* 5 */ "Already exists", - /* 6 */ "Invalid edge vector", + /* 6 */ "Invalid edge vector", /* removed in 1.0 */ /* 7 */ "Invalid vertex ID", - /* 8 */ "Non-square matrix", + /* 8 */ "Invalid edge ID", /* 9 */ "Invalid mode", /* 10 */ "File operation error", /* 11 */ "Unfold infinite iterator", @@ -131,7 +131,7 @@ static const char *igraph_i_error_strings[] = { "is to increase the size of NCV relative to NEV", /* 41 */ "The Schur form computed by LAPACK routine dlahqr " "could not be reordered by LAPACK routine dtrsen.", - /* 42 */ "Big integer division by zero", + /* 42 */ "Big integer division by zero", /* removed in 1.0 */ /* 43 */ "GLPK Error, GLP_EBOUND", /* 44 */ "GLPK Error, GLP_EROOT", /* 45 */ "GLPK Error, GLP_ENOPFS", @@ -140,11 +140,10 @@ static const char *igraph_i_error_strings[] = { /* 48 */ "GLPK Error, GLP_EMIPGAP", /* 49 */ "GLPK Error, GLP_ETMLIM", /* 50 */ "GLPK Error, GLP_STOP", - /* 51 */ "Internal attribute handler error", + /* 51 */ "Internal attribute handler error", /* removed in 1.0 */ /* 52 */ "Unimplemented attribute combination for this type", /* 53 */ "LAPACK call resulted in an error", - /* 54 */ "Internal DrL error; this error should never be visible to the user, " - "please report this error along with the steps to reproduce it.", + /* 54 */ "Internal DrL error", /* removed in 1.0 */ /* 55 */ "Integer or double overflow", /* 56 */ "Internal GPLK error", /* 57 */ "CPU time exceeded", diff --git a/src/vendor/cigraph/src/core/heap.pmt b/src/vendor/cigraph/src/core/heap.pmt index 0aa14c97030..72c0cdd2e32 100644 --- a/src/vendor/cigraph/src/core/heap.pmt +++ b/src/vendor/cigraph/src/core/heap.pmt @@ -62,7 +62,6 @@ igraph_error_t FUNCTION(igraph_heap, init)(TYPE(igraph_heap)* h, igraph_integer_ IGRAPH_CHECK_OOM(h->stor_begin, "Cannot initialize heap."); h->stor_end = h->stor_begin + capacity; h->end = h->stor_begin; - h->destroy = true; return IGRAPH_SUCCESS; } @@ -88,7 +87,6 @@ igraph_error_t FUNCTION(igraph_heap, init_array)(TYPE(igraph_heap) *h, const BAS IGRAPH_CHECK_OOM(h->stor_begin, "Cannot initialize heap from array."); h->stor_end = h->stor_begin + len; h->end = h->stor_end; - h->destroy = true; memcpy(h->stor_begin, data, (size_t) len * sizeof(BASE)); @@ -108,10 +106,8 @@ igraph_error_t FUNCTION(igraph_heap, init_array)(TYPE(igraph_heap) *h, const BAS */ void FUNCTION(igraph_heap, destroy)(TYPE(igraph_heap)* h) { - if (h->destroy) { - if (h->stor_begin != NULL) { - IGRAPH_FREE(h->stor_begin); /* sets to NULL */ - } + if (h->stor_begin != NULL) { + IGRAPH_FREE(h->stor_begin); /* sets to NULL */ } } diff --git a/src/vendor/cigraph/src/core/indheap.c b/src/vendor/cigraph/src/core/indheap.c index b4ee00e4b54..7e30b55aa84 100644 --- a/src/vendor/cigraph/src/core/indheap.c +++ b/src/vendor/cigraph/src/core/indheap.c @@ -69,7 +69,6 @@ igraph_error_t igraph_indheap_init(igraph_indheap_t* h, igraph_integer_t alloc_s h->stor_end = h->stor_begin + alloc_size; h->end = h->stor_begin; - h->destroy = true; return IGRAPH_SUCCESS; } @@ -106,7 +105,6 @@ igraph_error_t igraph_indheap_init_array(igraph_indheap_t *h, const igraph_real_ } h->stor_end = h->stor_begin + alloc_size; h->end = h->stor_begin + len; - h->destroy = true; memcpy(h->stor_begin, data, (size_t) len * sizeof(igraph_real_t)); for (i = 0; i < len; i++) { @@ -125,16 +123,14 @@ igraph_error_t igraph_indheap_init_array(igraph_indheap_t *h, const igraph_real_ void igraph_indheap_destroy(igraph_indheap_t* h) { IGRAPH_ASSERT(h != 0); - if (h->destroy) { - if (h->stor_begin != 0) { - IGRAPH_FREE(h->stor_begin); - h->stor_begin = 0; - } - if (h->index_begin != 0) { - IGRAPH_FREE(h->index_begin); - h->index_begin = 0; - } - } + if (h->stor_begin != 0) { + IGRAPH_FREE(h->stor_begin); + h->stor_begin = 0; + } + if (h->index_begin != 0) { + IGRAPH_FREE(h->index_begin); + h->index_begin = 0; + } } /** @@ -451,7 +447,6 @@ igraph_error_t igraph_d_indheap_init(igraph_d_indheap_t* h, igraph_integer_t all } h->stor_end = h->stor_begin + alloc_size; h->end = h->stor_begin; - h->destroy = true; h->index_begin = IGRAPH_CALLOC(alloc_size, igraph_integer_t); if (h->index_begin == 0) { IGRAPH_FREE(h->stor_begin); @@ -478,20 +473,18 @@ igraph_error_t igraph_d_indheap_init(igraph_d_indheap_t* h, igraph_integer_t all void igraph_d_indheap_destroy(igraph_d_indheap_t* h) { IGRAPH_ASSERT(h != 0); - if (h->destroy) { - if (h->stor_begin != 0) { - IGRAPH_FREE(h->stor_begin); - h->stor_begin = 0; - } - if (h->index_begin != 0) { - IGRAPH_FREE(h->index_begin); - h->index_begin = 0; - } - if (h->index2_begin != 0) { - IGRAPH_FREE(h->index2_begin); - h->index2_begin = 0; - } - } + if (h->stor_begin != 0) { + IGRAPH_FREE(h->stor_begin); + h->stor_begin = 0; + } + if (h->index_begin != 0) { + IGRAPH_FREE(h->index_begin); + h->index_begin = 0; + } + if (h->index2_begin != 0) { + IGRAPH_FREE(h->index2_begin); + h->index2_begin = 0; + } } /** diff --git a/src/vendor/cigraph/src/core/indheap.h b/src/vendor/cigraph/src/core/indheap.h index 9f340c33301..41c37587348 100644 --- a/src/vendor/cigraph/src/core/indheap.h +++ b/src/vendor/cigraph/src/core/indheap.h @@ -42,11 +42,10 @@ typedef struct s_indheap { igraph_real_t* stor_begin; igraph_real_t* stor_end; igraph_real_t* end; - igraph_bool_t destroy; igraph_integer_t* index_begin; } igraph_indheap_t; -#define IGRAPH_INDHEAP_NULL { 0,0,0,0,0 } +#define IGRAPH_INDHEAP_NULL { 0,0,0,0 } igraph_error_t igraph_indheap_init(igraph_indheap_t* h, igraph_integer_t size); igraph_error_t igraph_indheap_init_array(igraph_indheap_t *t, const igraph_real_t *data, igraph_integer_t len); @@ -81,13 +80,12 @@ typedef struct s_indheap_d { igraph_real_t* stor_begin; igraph_real_t* stor_end; igraph_real_t* end; - igraph_bool_t destroy; igraph_integer_t* index_begin; igraph_integer_t* index2_begin; } igraph_d_indheap_t; -#define IGRAPH_D_INDHEAP_NULL { 0,0,0,0,0,0 } +#define IGRAPH_D_INDHEAP_NULL { 0,0,0,0,0 } IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_d_indheap_init(igraph_d_indheap_t *h, igraph_integer_t size); IGRAPH_PRIVATE_EXPORT void igraph_d_indheap_destroy(igraph_d_indheap_t *h); diff --git a/src/vendor/cigraph/src/core/interruption.c b/src/vendor/cigraph/src/core/interruption.c index 794220389ac..c1aacb62dd3 100644 --- a/src/vendor/cigraph/src/core/interruption.c +++ b/src/vendor/cigraph/src/core/interruption.c @@ -24,13 +24,13 @@ #include "igraph_interrupt.h" #include "config.h" -IGRAPH_THREAD_LOCAL igraph_interruption_handler_t *igraph_i_interruption_handler = 0; +IGRAPH_THREAD_LOCAL igraph_interruption_handler_t *igraph_i_interruption_handler = NULL; -igraph_error_t igraph_allow_interruption(void *data) { +igraph_bool_t igraph_allow_interruption(void) { if (igraph_i_interruption_handler) { - return igraph_i_interruption_handler(data); + return igraph_i_interruption_handler(); } - return IGRAPH_SUCCESS; + return false; } igraph_interruption_handler_t *igraph_set_interruption_handler (igraph_interruption_handler_t *new_handler) { diff --git a/src/vendor/cigraph/src/core/interruption.h b/src/vendor/cigraph/src/core/interruption.h index 98cbafbf3c7..5b91717bc36 100644 --- a/src/vendor/cigraph/src/core/interruption.h +++ b/src/vendor/cigraph/src/core/interruption.h @@ -37,16 +37,15 @@ extern IGRAPH_THREAD_LOCAL igraph_interruption_handler_t *igraph_i_interruption_ * \brief * * This macro should be called when interruption is allowed. It calls - * \ref igraph_allow_interruption() with the proper parameters and if that returns - * anything but \c IGRAPH_SUCCESS then - * the macro returns the "calling" function as well, with the proper - * error code (\c IGRAPH_INTERRUPTED). + * \ref igraph_allow_interruption() and if that returns anything but + * \c IGRAPH_SUCCESS then the macro returns the "calling" function as well, + * with the proper error code (\c IGRAPH_INTERRUPTED). */ #define IGRAPH_ALLOW_INTERRUPTION() \ do { \ if (igraph_i_interruption_handler) { \ - if (igraph_allow_interruption(NULL) != IGRAPH_SUCCESS) { \ + if (igraph_allow_interruption()) { \ return IGRAPH_INTERRUPTED; \ } \ } \ diff --git a/src/vendor/cigraph/src/core/matrix.pmt b/src/vendor/cigraph/src/core/matrix.pmt index 64418149cf5..b640d5b0f46 100644 --- a/src/vendor/cigraph/src/core/matrix.pmt +++ b/src/vendor/cigraph/src/core/matrix.pmt @@ -1113,12 +1113,11 @@ igraph_error_t FUNCTION(igraph_matrix, cbind)(TYPE(igraph_matrix) *to, * The contents of the two matrices will be swapped. * \param m1 The first matrix. * \param m2 The second matrix. - * \return Error code. * * Time complexity: O(1). */ -igraph_error_t FUNCTION(igraph_matrix, swap)(TYPE(igraph_matrix) *m1, TYPE(igraph_matrix) *m2) { +void FUNCTION(igraph_matrix, swap)(TYPE(igraph_matrix) *m1, TYPE(igraph_matrix) *m2) { igraph_integer_t tmp; tmp = m1->nrow; @@ -1129,9 +1128,7 @@ igraph_error_t FUNCTION(igraph_matrix, swap)(TYPE(igraph_matrix) *m1, TYPE(igrap m1->ncol = m2->ncol; m2->ncol = tmp; - IGRAPH_CHECK(FUNCTION(igraph_vector, swap)(&m1->data, &m2->data)); - - return IGRAPH_SUCCESS; + FUNCTION(igraph_vector, swap)(&m1->data, &m2->data); } /** diff --git a/src/vendor/cigraph/src/core/sparsemat.c b/src/vendor/cigraph/src/core/sparsemat.c index 524c109cb03..9d03046efc5 100644 --- a/src/vendor/cigraph/src/core/sparsemat.c +++ b/src/vendor/cigraph/src/core/sparsemat.c @@ -27,10 +27,8 @@ #include "igraph_constructors.h" #include "igraph_interface.h" #include "igraph_memory.h" +#include "igraph_misc.h" /* IGRAPH_STATIC_ASSERT */ #include "igraph_types.h" -#include "igraph_vector_ptr.h" - -#include "internal/hacks.h" /* IGRAPH_STATIC_ASSERT */ #include #include @@ -1010,7 +1008,7 @@ igraph_error_t igraph_sparsemat_lsolve(const igraph_sparsemat_t *L, igraph_vector_t *res) { if (L->cs->m != L->cs->n) { - IGRAPH_ERROR("Cannot perform lower triangular solve", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Cannot perform lower triangular solve on non-square matrix.", IGRAPH_EINVAL); } if (res != b) { @@ -1018,7 +1016,7 @@ igraph_error_t igraph_sparsemat_lsolve(const igraph_sparsemat_t *L, } if (! cs_lsolve(L->cs, VECTOR(*res))) { - IGRAPH_ERROR("Cannot perform lower triangular solve", IGRAPH_FAILURE); + IGRAPH_ERROR("Cannot perform lower triangular solve.", IGRAPH_FAILURE); } return IGRAPH_SUCCESS; @@ -1044,8 +1042,10 @@ igraph_error_t igraph_sparsemat_ltsolve(const igraph_sparsemat_t *L, igraph_vector_t *res) { if (L->cs->m != L->cs->n) { - IGRAPH_ERROR("Cannot perform transposed lower triangular solve", - IGRAPH_NONSQUARE); + IGRAPH_ERROR( + "Cannot perform transposed lower triangular solve on non-square matrix.", + IGRAPH_EINVAL + ); } if (res != b) { @@ -1053,7 +1053,7 @@ igraph_error_t igraph_sparsemat_ltsolve(const igraph_sparsemat_t *L, } if (!cs_ltsolve(L->cs, VECTOR(*res))) { - IGRAPH_ERROR("Cannot perform lower triangular solve", IGRAPH_FAILURE); + IGRAPH_ERROR("Cannot perform lower triangular solve.", IGRAPH_FAILURE); } return IGRAPH_SUCCESS; @@ -1078,7 +1078,10 @@ igraph_error_t igraph_sparsemat_usolve(const igraph_sparsemat_t *U, igraph_vector_t *res) { if (U->cs->m != U->cs->n) { - IGRAPH_ERROR("Cannot perform upper triangular solve", IGRAPH_NONSQUARE); + IGRAPH_ERROR( + "Cannot perform upper triangular solve on non-square matrix.", + IGRAPH_EINVAL + ); } if (res != b) { @@ -1086,7 +1089,7 @@ igraph_error_t igraph_sparsemat_usolve(const igraph_sparsemat_t *U, } if (! cs_usolve(U->cs, VECTOR(*res))) { - IGRAPH_ERROR("Cannot perform upper triangular solve", IGRAPH_FAILURE); + IGRAPH_ERROR("Cannot perform upper triangular solve.", IGRAPH_FAILURE); } return IGRAPH_SUCCESS; @@ -1112,8 +1115,10 @@ igraph_error_t igraph_sparsemat_utsolve(const igraph_sparsemat_t *U, igraph_vector_t *res) { if (U->cs->m != U->cs->n) { - IGRAPH_ERROR("Cannot perform transposed upper triangular solve", - IGRAPH_NONSQUARE); + IGRAPH_ERROR( + "Cannot perform transposed upper triangular solve on non-square matrix.", + IGRAPH_EINVAL + ); } if (res != b) { @@ -1121,7 +1126,7 @@ igraph_error_t igraph_sparsemat_utsolve(const igraph_sparsemat_t *U, } if (!cs_utsolve(U->cs, VECTOR(*res))) { - IGRAPH_ERROR("Cannot perform transposed upper triangular solve", + IGRAPH_ERROR("Cannot perform transposed upper triangular solve.", IGRAPH_FAILURE); } @@ -1151,8 +1156,10 @@ igraph_error_t igraph_sparsemat_cholsol(const igraph_sparsemat_t *A, igraph_integer_t order) { if (A->cs->m != A->cs->n) { - IGRAPH_ERROR("Cannot perform sparse symmetric solve", - IGRAPH_NONSQUARE); + IGRAPH_ERROR( + "Cannot perform sparse symmetric solve on non-square matrix.", + IGRAPH_EINVAL + ); } if (res != b) { @@ -1160,7 +1167,7 @@ igraph_error_t igraph_sparsemat_cholsol(const igraph_sparsemat_t *A, } if (! cs_cholsol(order, A->cs, VECTOR(*res))) { - IGRAPH_ERROR("Cannot perform sparse symmetric solve", IGRAPH_FAILURE); + IGRAPH_ERROR("Cannot perform sparse symmetric solve.", IGRAPH_FAILURE); } return IGRAPH_SUCCESS; @@ -1193,8 +1200,7 @@ igraph_error_t igraph_sparsemat_lusol(const igraph_sparsemat_t *A, igraph_real_t tol) { if (A->cs->m != A->cs->n) { - IGRAPH_ERROR("Cannot perform LU solve", - IGRAPH_NONSQUARE); + IGRAPH_ERROR("Cannot perform LU solve on non-square matrix.", IGRAPH_EINVAL); } if (res != b) { @@ -1202,7 +1208,7 @@ igraph_error_t igraph_sparsemat_lusol(const igraph_sparsemat_t *A, } if (! cs_lusol(order, A->cs, VECTOR(*res), tol)) { - IGRAPH_ERROR("Cannot perform LU solve", IGRAPH_FAILURE); + IGRAPH_ERROR("Cannot perform LU solve.", IGRAPH_FAILURE); } return IGRAPH_SUCCESS; @@ -1221,7 +1227,7 @@ static igraph_error_t igraph_i_sparsemat_cc(igraph_t *graph, const igraph_sparse igraph_integer_t e = 0; if (no_of_nodes != A->cs->n) { - IGRAPH_ERROR("Cannot create graph object", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Cannot create graph object from non-square matrix.", IGRAPH_EINVAL); } IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); @@ -1258,7 +1264,7 @@ static igraph_error_t igraph_i_sparsemat_triplet(igraph_t *graph, const igraph_s igraph_integer_t e; if (no_of_nodes != A->cs->n) { - IGRAPH_ERROR("Cannot create graph object", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Cannot create graph object from non-square matrix.", IGRAPH_EINVAL); } IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); @@ -1368,49 +1374,54 @@ igraph_error_t igraph_weighted_sparsemat(igraph_t *graph, const igraph_sparsemat igraph_bool_t loops) { igraph_vector_int_t edges; - igraph_vector_t weights; CS_INT pot_edges = igraph_i_sparsemat_count_elements(A); const char* default_attr = "weight"; - igraph_vector_ptr_t attr_vec; + igraph_attribute_record_list_t attrs; igraph_attribute_record_t attr_rec; CS_INT no_of_nodes = A->cs->m; if (no_of_nodes != A->cs->n) { - IGRAPH_ERROR("Cannot create graph object", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Cannot create graph object from non-square matrix.", IGRAPH_EINVAL); } IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, pot_edges * 2); - IGRAPH_VECTOR_INIT_FINALLY(&weights, pot_edges); - IGRAPH_VECTOR_PTR_INIT_FINALLY(&attr_vec, 1); + /* Prepare attribute record list */ + IGRAPH_CHECK(igraph_attribute_record_list_init(&attrs, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &attrs); + + /* Prepare attribute record */ + IGRAPH_CHECK(igraph_attribute_record_init( + &attr_rec, attr ? attr : default_attr, IGRAPH_ATTRIBUTE_NUMERIC + )); + IGRAPH_FINALLY(igraph_attribute_record_destroy, &attr_rec); + + /* Convert sparse matrix, storing weights in the attribute record */ if (igraph_sparsemat_is_cc(A)) { IGRAPH_CHECK(igraph_i_weighted_sparsemat_cc(A, directed, attr, loops, - &edges, &weights)); + &edges, attr_rec.value.as_vector)); } else { IGRAPH_CHECK(igraph_i_weighted_sparsemat_triplet(A, directed, attr, loops, &edges, - &weights)); + attr_rec.value.as_vector)); } - /* Prepare attribute record */ - attr_rec.name = attr ? attr : default_attr; - attr_rec.type = IGRAPH_ATTRIBUTE_NUMERIC; - attr_rec.value = &weights; - VECTOR(attr_vec)[0] = &attr_rec; + /* Transfer ownership of attribute record to attribute record list */ + IGRAPH_CHECK(igraph_attribute_record_list_push_back(&attrs, &attr_rec)); + IGRAPH_FINALLY_CLEAN(1); /* Create graph */ IGRAPH_CHECK(igraph_empty(graph, no_of_nodes, directed)); IGRAPH_FINALLY(igraph_destroy, graph); if (igraph_vector_int_size(&edges) > 0) { - IGRAPH_CHECK(igraph_add_edges(graph, &edges, &attr_vec)); + IGRAPH_CHECK(igraph_add_edges(graph, &edges, &attrs)); } IGRAPH_FINALLY_CLEAN(1); /* Cleanup */ + igraph_attribute_record_list_destroy(&attrs); igraph_vector_int_destroy(&edges); - igraph_vector_destroy(&weights); - igraph_vector_ptr_destroy(&attr_vec); - IGRAPH_FINALLY_CLEAN(3); + IGRAPH_FINALLY_CLEAN(2); return IGRAPH_SUCCESS; } @@ -1703,11 +1714,11 @@ igraph_error_t igraph_sparsemat_arpack_rssolve(const igraph_sparsemat_t *A, igraph_integer_t n = igraph_sparsemat_nrow(A); if (n != igraph_sparsemat_ncol(A)) { - IGRAPH_ERROR("Non-square matrix for ARPACK", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Non-square matrix for ARPACK.", IGRAPH_EINVAL); } if (n > INT_MAX) { - IGRAPH_ERROR("Matrix too large for ARPACK", IGRAPH_EOVERFLOW); + IGRAPH_ERROR("Matrix too large for ARPACK.", IGRAPH_EOVERFLOW); } if (options == 0) { @@ -1807,11 +1818,11 @@ igraph_error_t igraph_sparsemat_arpack_rnsolve(const igraph_sparsemat_t *A, igraph_integer_t n = igraph_sparsemat_nrow(A); if (n > INT_MAX) { - IGRAPH_ERROR("Matrix too large for ARPACK", IGRAPH_EOVERFLOW); + IGRAPH_ERROR("Matrix too large for ARPACK.", IGRAPH_EOVERFLOW); } if (n != igraph_sparsemat_ncol(A)) { - IGRAPH_ERROR("Non-square matrix for ARPACK", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Non-square matrix for ARPACK.", IGRAPH_EINVAL); } if (options == 0) { diff --git a/src/vendor/cigraph/src/core/strvector.c b/src/vendor/cigraph/src/core/strvector.c index eb4bc2ea782..31fe27aa69f 100644 --- a/src/vendor/cigraph/src/core/strvector.c +++ b/src/vendor/cigraph/src/core/strvector.c @@ -21,8 +21,9 @@ */ -#include "igraph_types.h" #include "igraph_strvector.h" + +#include "igraph_types.h" #include "igraph_memory.h" #include "igraph_error.h" @@ -70,7 +71,7 @@ igraph_error_t igraph_strvector_init(igraph_strvector_t *sv, igraph_integer_t size) { - sv->stor_begin = IGRAPH_CALLOC(size, char*); + sv->stor_begin = IGRAPH_CALLOC(size, const char *); IGRAPH_CHECK_OOM(sv->stor_begin, "Cannot initialize string vector."); sv->stor_end = sv->stor_begin + size; @@ -93,10 +94,9 @@ igraph_error_t igraph_strvector_init(igraph_strvector_t *sv, igraph_integer_t si */ void igraph_strvector_destroy(igraph_strvector_t *sv) { - char **ptr; IGRAPH_ASSERT(sv != NULL); IGRAPH_ASSERT(sv->stor_begin != NULL); - for (ptr = sv->stor_begin; ptr < sv->end; ptr++) { + for (const char **ptr = sv->stor_begin; ptr < sv->end; ptr++) { IGRAPH_FREE(*ptr); } IGRAPH_FREE(sv->stor_begin); @@ -172,9 +172,9 @@ igraph_error_t igraph_strvector_set_len(igraph_strvector_t *sv, igraph_integer_t char *tmp = IGRAPH_REALLOC(sv->stor_begin[idx], len + 1, char); IGRAPH_CHECK_OOM(tmp, "Cannot reserve space for new item in string vector."); + memcpy(tmp, value, len * sizeof(char)); + tmp[len] = '\0'; sv->stor_begin[idx] = tmp; - memcpy(sv->stor_begin[idx], value, len * sizeof(char)); - sv->stor_begin[idx][len] = '\0'; } return IGRAPH_SUCCESS; @@ -250,7 +250,7 @@ igraph_error_t igraph_strvector_init_copy(igraph_strvector_t *to, const igraph_strvector_t *from) { igraph_integer_t from_size = igraph_strvector_size(from); - to->stor_begin = IGRAPH_CALLOC(from_size, char*); + to->stor_begin = IGRAPH_CALLOC(from_size, const char *); IGRAPH_CHECK_OOM(to->stor_begin, "Cannot copy string vector."); for (igraph_integer_t i = 0; i < from_size; i++) { @@ -311,10 +311,10 @@ igraph_error_t igraph_strvector_copy(igraph_strvector_t *to, igraph_error_t igraph_strvector_append(igraph_strvector_t *to, const igraph_strvector_t *from) { - igraph_integer_t len1 = igraph_strvector_size(to), len2 = igraph_strvector_size(from); + const igraph_integer_t len1 = igraph_strvector_size(to), len2 = igraph_strvector_size(from); igraph_integer_t newlen; igraph_bool_t error = false; - char *tmp; + const char *tmp; IGRAPH_SAFE_ADD(len1, len2, &newlen); IGRAPH_CHECK(igraph_strvector_reserve(to, newlen)); @@ -362,7 +362,7 @@ igraph_error_t igraph_strvector_append(igraph_strvector_t *to, * where l1 and l2 are the lengths of \p to and \from respectively. */ igraph_error_t igraph_strvector_merge(igraph_strvector_t *to, igraph_strvector_t *from) { - char **p1, **p2, **pe; + const char **p1, **p2, **pe; igraph_integer_t newlen; IGRAPH_SAFE_ADD(igraph_strvector_size(to), igraph_strvector_size(from), &newlen); @@ -431,7 +431,7 @@ igraph_error_t igraph_strvector_resize(igraph_strvector_t *sv, igraph_integer_t sv->end = sv->stor_begin + newsize; } else if (newsize > oldsize) { IGRAPH_CHECK(igraph_strvector_reserve(sv, newsize)); - memset(sv->stor_begin + oldsize, 0, toadd * sizeof(char *)); + memset(sv->stor_begin + oldsize, 0, toadd * sizeof(const char *)); sv->end = sv->stor_begin + newsize; } @@ -484,13 +484,12 @@ igraph_integer_t igraph_strvector_capacity(const igraph_strvector_t *sv) { igraph_error_t igraph_strvector_reserve(igraph_strvector_t *sv, igraph_integer_t capacity) { igraph_integer_t current_capacity = igraph_strvector_capacity(sv); - char **tmp; if (capacity <= current_capacity) { return IGRAPH_SUCCESS; } - tmp = IGRAPH_REALLOC(sv->stor_begin, capacity, char *); + const char **tmp = IGRAPH_REALLOC(sv->stor_begin, capacity, const char *); IGRAPH_CHECK_OOM(tmp, "Cannot reserve space for new items in string vector."); sv->end = tmp + (sv->end - sv->stor_begin); @@ -516,14 +515,12 @@ igraph_error_t igraph_strvector_reserve(igraph_strvector_t *sv, igraph_integer_t */ void igraph_strvector_resize_min(igraph_strvector_t *sv) { - igraph_integer_t size; - char **tmp; if (sv->stor_end == sv->end) { return; } - size = (sv->end - sv->stor_begin); - tmp = IGRAPH_REALLOC(sv->stor_begin, size, char *); + const igraph_integer_t size = (sv->end - sv->stor_begin); + const char **tmp = IGRAPH_REALLOC(sv->stor_begin, size, const char *); if (tmp != NULL) { sv->stor_begin = tmp; @@ -586,7 +583,7 @@ static igraph_error_t igraph_i_strvector_expand_if_full(igraph_strvector_t *sv) igraph_error_t igraph_strvector_push_back(igraph_strvector_t *sv, const char *value) { IGRAPH_CHECK(igraph_i_strvector_expand_if_full(sv)); - char *tmp = strdup(value); + const char *tmp = strdup(value); IGRAPH_CHECK_OOM(tmp, "Cannot push new string to string vector."); *sv->end = tmp; sv->end++; @@ -613,7 +610,7 @@ igraph_error_t igraph_strvector_push_back_len( const char *value, igraph_integer_t len) { IGRAPH_CHECK(igraph_i_strvector_expand_if_full(sv)); - char *tmp = strndup(value, len); + const char *tmp = strndup(value, len); if (! tmp) { IGRAPH_ERROR("Cannot add string to string vector.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ } @@ -697,3 +694,42 @@ igraph_error_t igraph_strvector_index(const igraph_strvector_t *sv, return IGRAPH_SUCCESS; } + +/** + * \ingroup strvector + * \function igraph_strvector_update + * \brief Updates a string vector from another one. + * + * After this operation the contents of \p to will be exactly the same + * as that of \p from. The vector \p to will be resized if it was originally + * shorter or longer than \p from. + * + * \param to The string vector to update. + * \param from The string vector to update from. + * \return Error code. + */ +igraph_error_t igraph_strvector_update( + igraph_strvector_t *to, const igraph_strvector_t *from +) { + igraph_strvector_clear(to); + IGRAPH_CHECK(igraph_strvector_append(to, from)); + return IGRAPH_SUCCESS; +} + +/** + * \ingroup strvector + * \function igraph_strvector_swap + * \brief Swaps all elements of two string vectors. + * + * \param v1 The first string vector. + * \param v2 The second string vector. + * + * Time complexity: O(1). + */ +void igraph_strvector_swap(igraph_strvector_t *v1, igraph_strvector_t *v2) { + igraph_strvector_t tmp; + + tmp = *v1; + *v1 = *v2; + *v2 = tmp; +} diff --git a/src/vendor/cigraph/src/core/typed_list.pmt b/src/vendor/cigraph/src/core/typed_list.pmt index 75aaa80e8a4..1ffc3421355 100644 --- a/src/vendor/cigraph/src/core/typed_list.pmt +++ b/src/vendor/cigraph/src/core/typed_list.pmt @@ -65,6 +65,8 @@ * _item_ in the vector */ #if defined(BASE_GRAPH) #define ITEM_FUNCTION(f) CONCAT2x(igraph,f) + #elif defined(BASE_ATTRIBUTE_RECORD) + #define ITEM_FUNCTION(f) CONCAT2x(igraph_attribute_record,f) #endif #endif @@ -117,6 +119,38 @@ igraph_error_t FUNCTION(init)(TYPE* v, igraph_integer_t size) { return IGRAPH_SUCCESS; } +/** + * \ingroup vector_list + * \function igraph_vector_list_init_copy + * \brief Initializes a list of vectors from another list of vectors (constructor). + * + * + * The contents of the existing list will be copied to the new one. + * \param to Pointer to a not yet initialized list of vectors. + * \param from The original list of vectors to copy. + * \return Error code: + * \c IGRAPH_ENOMEM if there is not enough memory. + * + * Time complexity: operating system dependent, usually O(nm), n is the size of + * the list, m is the size of each element in the list, assuming that copying a + * single item takes O(m) time. + */ + +igraph_error_t FUNCTION(init_copy)(TYPE* to, const TYPE* from) { + igraph_integer_t i, size = FUNCTION(size)(from); + + IGRAPH_CHECK(FUNCTION(init)(to, 0)); + IGRAPH_FINALLY(FUNCTION(destroy), to); + + for (i = 0; i < size; i++) { + IGRAPH_CHECK(FUNCTION(push_back_copy)(to, FUNCTION(get_ptr)(from, i))); + } + + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + /** * \ingroup vector_list * \function igraph_vector_list_destroy diff --git a/src/vendor/cigraph/src/core/vector.pmt b/src/vendor/cigraph/src/core/vector.pmt index 6cb5c6fcbb5..6f841831766 100644 --- a/src/vendor/cigraph/src/core/vector.pmt +++ b/src/vendor/cigraph/src/core/vector.pmt @@ -1879,8 +1879,7 @@ igraph_error_t FUNCTION(igraph_vector, move_interval2)(TYPE(igraph_vector) *v, * are in the interval, false (zero) otherwise. If any element is NaN, it will * return \c 0 (=false). * - * Time complexity: O(n), the number - * of elements in the vector. + * Time complexity: O(n), the number of elements in the vector. */ igraph_bool_t FUNCTION(igraph_vector, isininterval)(const TYPE(igraph_vector) *v, @@ -2553,20 +2552,17 @@ igraph_error_t FUNCTION(igraph_vector, update)(TYPE(igraph_vector) *to, * * \param v1 The first vector. * \param v2 The second vector. - * \return Error code. * * Time complexity: O(1). */ -igraph_error_t FUNCTION(igraph_vector, swap)(TYPE(igraph_vector) *v1, TYPE(igraph_vector) *v2) { +void FUNCTION(igraph_vector, swap)(TYPE(igraph_vector) *v1, TYPE(igraph_vector) *v2) { TYPE(igraph_vector) tmp; tmp = *v1; *v1 = *v2; *v2 = tmp; - - return IGRAPH_SUCCESS; } /** @@ -2629,7 +2625,6 @@ igraph_error_t FUNCTION(igraph_vector, reverse)(TYPE(igraph_vector) *v) { * these generators is less than the number of possible permutations * of the vector if the vector is long enough. * \param v The vector object. - * \return Error code, currently always \c IGRAPH_SUCCESS. * * Time complexity: O(n), * n is the number of elements in the @@ -2650,7 +2645,7 @@ igraph_error_t FUNCTION(igraph_vector, reverse)(TYPE(igraph_vector) *v) { * \example examples/simple/igraph_fisher_yates_shuffle.c */ -igraph_error_t FUNCTION(igraph_vector, shuffle)(TYPE(igraph_vector) *v) { +void FUNCTION(igraph_vector, shuffle)(TYPE(igraph_vector) *v) { igraph_integer_t n = FUNCTION(igraph_vector, size)(v); igraph_integer_t k; BASE dummy; @@ -2664,8 +2659,6 @@ igraph_error_t FUNCTION(igraph_vector, shuffle)(TYPE(igraph_vector) *v) { VECTOR(*v)[k] = dummy; } RNG_END(); - - return IGRAPH_SUCCESS; } /** diff --git a/src/vendor/cigraph/src/flow/st-cuts.c b/src/vendor/cigraph/src/flow/st-cuts.c index 692b6f6878b..75a1a4a5eb0 100644 --- a/src/vendor/cigraph/src/flow/st-cuts.c +++ b/src/vendor/cigraph/src/flow/st-cuts.c @@ -596,9 +596,7 @@ igraph_error_t igraph_dominator_tree(const igraph_t *graph, igraph_vector_int_destroy(&edges); IGRAPH_FINALLY_CLEAN(1); - IGRAPH_I_ATTRIBUTE_DESTROY(domtree); - IGRAPH_I_ATTRIBUTE_COPY(domtree, graph, - /*graph=*/ true, /*vertex=*/ true, /*edge=*/ false); + IGRAPH_CHECK(igraph_i_attribute_copy(domtree, graph, true, true, /*edges=*/ false)); } if (!dom) { @@ -766,7 +764,7 @@ igraph_error_t igraph_i_all_st_cuts_pivot( IGRAPH_FINALLY_CLEAN(1); IGRAPH_FINALLY(igraph_destroy, &Sbar); - root = VECTOR(Sbar_map)[target] - 1; + root = VECTOR(Sbar_map)[target]; /* -------------------------------------------------------------*/ /* Construct the dominator tree of Sbar */ @@ -786,7 +784,7 @@ igraph_error_t igraph_i_all_st_cuts_pivot( IGRAPH_CHECK(igraph_vector_bool_init(&GammaS, no_of_nodes)); IGRAPH_FINALLY(igraph_vector_bool_destroy, &GammaS); if (igraph_marked_queue_int_size(S) == 0) { - VECTOR(GammaS)[VECTOR(Sbar_map)[source] - 1] = true; + VECTOR(GammaS)[VECTOR(Sbar_map)[source]] = true; } else { for (i = 0; i < no_of_nodes; i++) { if (igraph_marked_queue_int_iselement(S, i)) { @@ -841,7 +839,7 @@ igraph_error_t igraph_i_all_st_cuts_pivot( Nu(v) contains all vertices that are dominated by v, for every v, this is a subtree of the dominator tree, rooted at v. The different subtrees are disjoint. */ - igraph_integer_t min = VECTOR(Sbar_map)[ VECTOR(M)[i] ] - 1; + igraph_integer_t min = VECTOR(Sbar_map)[ VECTOR(M)[i] ]; igraph_integer_t nuvsize, isvlen, j; IGRAPH_CHECK(igraph_dfs(&domtree, min, IGRAPH_IN, /*unreachable=*/ false, /*order=*/ &Nuv, diff --git a/src/vendor/cigraph/src/games/erdos_renyi.c b/src/vendor/cigraph/src/games/erdos_renyi.c index b7b2dbd6dee..ab0968bfda2 100644 --- a/src/vendor/cigraph/src/games/erdos_renyi.c +++ b/src/vendor/cigraph/src/games/erdos_renyi.c @@ -176,6 +176,63 @@ igraph_error_t igraph_erdos_renyi_game_gnp( return IGRAPH_SUCCESS; } +/** + * \ingroup generators + * \function igraph_erdos_renyi_game_gnm_multi + * \brief Generates a random (Erdős-Rényi) graph with multi-edges. + * + * \param graph Pointer to an uninitialized graph object. + * \param n The number of vertices in the graph. + * \param m The number of edges in the graph. + * \param directed Logical, whether to generate a directed graph. + * \param loops Logical, whether to generate loops (self) edges. + * \return Error code: + * \c IGRAPH_EINVAL: invalid \p n or \p m parameter. + * \c IGRAPH_ENOMEM: there is not enough + * memory for the operation. + * + * Time complexity: O(|V|+|E|), the + * number of vertices plus the number of edges in the graph. + */ +static igraph_error_t igraph_i_erdos_renyi_game_gnm_multi( + igraph_t *graph, igraph_integer_t n, igraph_integer_t m, + igraph_bool_t directed, igraph_bool_t loops +) { + + igraph_vector_int_t edges; + int iter = 0; + + /* No need for checking n or m here; it has already been done in + * igraph_erdos_renyi_game_gnm() */ + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, m * 2)); + + RNG_BEGIN(); + for (igraph_integer_t i = 0; i < m; i++) { + igraph_integer_t from, to; + from = RNG_INTEGER(0, n - 1); + if (loops) { + to = RNG_INTEGER(0, n - 1); + } else { + to = RNG_INTEGER(0, n - 2); + if (from == to) { + to = n - 1; + } + } + igraph_vector_int_push_back(&edges, from); /* reserved */ + igraph_vector_int_push_back(&edges, to); /* reserved */ + IGRAPH_ALLOW_INTERRUPTION_LIMITED(iter, 1 << 14); + } + RNG_END(); + + IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + /** * \ingroup generators * \function igraph_erdos_renyi_game_gnm @@ -189,6 +246,8 @@ igraph_error_t igraph_erdos_renyi_game_gnp( * \param m The number of edges in the graph. * \param directed Logical, whether to generate a directed graph. * \param loops Logical, whether to generate self-loops. + * \param multiple Logical, whether it is allowed to generate more than one + * edge between the same pair of vertices. * \return Error code: * \c IGRAPH_EINVAL: invalid \p n or \p m parameter. * \c IGRAPH_ENOMEM: there is not enough memory for the operation. @@ -203,7 +262,7 @@ igraph_error_t igraph_erdos_renyi_game_gnp( */ igraph_error_t igraph_erdos_renyi_game_gnm( igraph_t *graph, igraph_integer_t n, igraph_integer_t m, - igraph_bool_t directed, igraph_bool_t loops + igraph_bool_t directed, igraph_bool_t loops, igraph_bool_t multiple ) { /* This function uses doubles in its `s` vector, and for `maxedges` and `last`. @@ -225,6 +284,10 @@ igraph_error_t igraph_erdos_renyi_game_gnm( IGRAPH_ERROR("Invalid number of edges.", IGRAPH_EINVAL); } + if (multiple) { + return igraph_i_erdos_renyi_game_gnm_multi(graph, n, m, directed, loops); + } + if (m == 0.0 || no_of_nodes == 0) { IGRAPH_CHECK(igraph_empty(graph, n, directed)); } else { @@ -355,7 +418,7 @@ igraph_error_t igraph_erdos_renyi_game(igraph_t *graph, igraph_erdos_renyi_t typ if (type == IGRAPH_ERDOS_RENYI_GNP) { return igraph_erdos_renyi_game_gnp(graph, n, p_or_m, directed, loops); } else if (type == IGRAPH_ERDOS_RENYI_GNM) { - return igraph_erdos_renyi_game_gnm(graph, n, (igraph_integer_t) p_or_m, directed, loops); + return igraph_erdos_renyi_game_gnm(graph, n, (igraph_integer_t) p_or_m, directed, loops, IGRAPH_NO_MULTIPLE); } else { IGRAPH_ERROR("Invalid type", IGRAPH_EINVAL); } diff --git a/src/vendor/cigraph/src/games/sbm.c b/src/vendor/cigraph/src/games/sbm.c index 12cf6639536..7c92a637cef 100644 --- a/src/vendor/cigraph/src/games/sbm.c +++ b/src/vendor/cigraph/src/games/sbm.c @@ -86,8 +86,7 @@ igraph_error_t igraph_sbm_game(igraph_t *graph, igraph_integer_t n, /* ------------------------------------------------------------ */ if (igraph_matrix_ncol(pref_matrix) != no_blocks) { - IGRAPH_ERROR("Preference matrix is not square.", - IGRAPH_NONSQUARE); + IGRAPH_ERROR("Preference matrix is not square.", IGRAPH_EINVAL); } if (no_blocks > 0) { diff --git a/src/vendor/cigraph/src/games/static_fitness.c b/src/vendor/cigraph/src/games/static_fitness.c index 8c4c1f057dc..9236bd6a2e6 100644 --- a/src/vendor/cigraph/src/games/static_fitness.c +++ b/src/vendor/cigraph/src/games/static_fitness.c @@ -420,7 +420,7 @@ igraph_error_t igraph_static_power_law_game(igraph_t *graph, for (i = 0; i < no_of_nodes; i++, j--) { VECTOR(fitness_in)[i] = pow(j, alpha_in); } - IGRAPH_CHECK(igraph_vector_shuffle(&fitness_in)); + igraph_vector_shuffle(&fitness_in); IGRAPH_CHECK(igraph_static_fitness_game(graph, no_of_edges, &fitness_out, &fitness_in, loops, multiple)); diff --git a/src/vendor/cigraph/src/graph/attributes.c b/src/vendor/cigraph/src/graph/attributes.c index 731d628d9d3..1eb37e929ab 100644 --- a/src/vendor/cigraph/src/graph/attributes.c +++ b/src/vendor/cigraph/src/graph/attributes.c @@ -30,21 +30,602 @@ #include #include +/** + * \section about_attributes + * + * Attributes are numbers, boolean values or strings associated with + * the vertices or edges of a graph, or with the graph itself. E.g. you may + * label vertices with symbolic names or attach numeric weights to the edges + * of a graph. In addition to these three basic types, a custom object + * type is supported as well. + * + * igraph attributes are designed to be flexible and extensible. + * In igraph attributes are implemented via an interface abstraction: + * any type implementing the functions in the interface can be used + * for storing vertex, edge and graph attributes. This means that + * different attribute implementations can be used together with + * igraph. This is reasonable: if igraph is used from Python attributes can be + * of any Python type, from R all R types are allowed. There is also an + * experimental attribute implementation to be used when programming + * in C, but by default it is currently turned off. + * + * First we briefly look over how attribute handlers can be + * implemented. This is not something a user does every day. It is + * rather typically the job of the high level interface writers. (But + * it is possible to write an interface without implementing + * attributes.) Then we show the experimental C attribute handler. + */ + +/** + * \section about_attribute_table + * It is possible to attach an attribute handling + * interface to \a igraph. This is simply a table of functions, of + * type \ref igraph_attribute_table_t. These functions are invoked to + * notify the attribute handling code about the structural changes in + * a graph. See the documentation of this type for details. + * + * By default there is no attribute interface attached to \a igraph. + * To attach one, call \ref igraph_set_attribute_table with your new + * table. This is normally done on program startup, and is kept untouched + * for the program's lifetime. It must be done before any graph object + * is created, as graphs created with a given attribute handler + * cannot be manipulated while a different attribute handler is + * active. + */ + +/** + * \section about_attribute_record + * + * Functions in the attribute handler interface may refer to + * \em "attribute records" or \em "attribute record lists". An attribute record + * is simply a triplet consisting of an attribute name, an attribute type and + * a vector containing the values of the attribute. Attribute record lists are + * typed containers that contain a sequence of attribute records. Attribute + * record lists own the attribute records that they contain, and similarly, + * attribute records own the vectors contained in them. Destroying an attribute + * record destroys the vector of values inside it, and destroying an attribute + * record list destroys all attribute records in the list. + */ + +/** + * \section about_attribute_combination + * + * Several graph operations may collapse multiple vertices or edges into + * a single one. Attribute combination lists are used to indicate to the attribute + * handler how to combine the attributes of the original vertices or edges and + * how to derive the final attribute value that is to be assigned to the collapsed + * vertex or edge. For example, \ref igraph_simplify() removes loops and combines + * multiple edges into a single one; in case of a graph with an edge attribute + * named \c weight the attribute combination list can tell the attribute handler + * whether the weight of a collapsed edge should be the sum, the mean or some other + * function of the weights of the original edges that were collapsed into one. + * + * One attribute combination list may contain several attribute combination + * records, one for each vertex or edge attribute that is to be handled during the + * operation. + */ + +static void igraph_i_attribute_record_set_type( + igraph_attribute_record_t *attr, igraph_attribute_type_t type, void *ptr +); +static void igraph_i_attribute_record_destroy_values(igraph_attribute_record_t *attr); + +/** + * \function igraph_attribute_record_init + * \brief Initializes an attribute record with a given name and type. + * + * \param attr the attribute record to initialize + * \param name name of the attribute + * \param type type of the attribute + * \return Error code: + * \c IGRAPH_ENOMEM if there is not enough memory. + * + * Time complexity: O(1). + */ +igraph_error_t igraph_attribute_record_init( + igraph_attribute_record_t *attr, const char* name, igraph_attribute_type_t type +) { + attr->name = NULL; + attr->type = IGRAPH_ATTRIBUTE_UNSPECIFIED; + attr->value.as_raw = NULL; + attr->default_value.string = NULL; + + IGRAPH_CHECK(igraph_attribute_record_set_name(attr, name)); + IGRAPH_CHECK(igraph_attribute_record_set_type(attr, type)); + + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_attribute_record_init_copy + * \brief Initializes an attribute record by copying another record. + * + * + * Copies made by this function are deep copies: a full copy of the value + * vector contained in the record is placed in the new record so they become + * independent of each other. + * + * \param to the attribute record to initialize + * \param from the attribute record to copy data from + * \return Error code: + * \c IGRAPH_ENOMEM if there is not enough memory. + * + * Time complexity: operating system dependent, usually O(n), where n is the + * size of the value vector in the attribute record. + */ +igraph_error_t igraph_attribute_record_init_copy( + igraph_attribute_record_t *to, const igraph_attribute_record_t *from +) { + IGRAPH_CHECK(igraph_attribute_record_init(to, from->name, from->type)); + + switch (from->type) { + case IGRAPH_ATTRIBUTE_NUMERIC: + IGRAPH_CHECK(igraph_vector_update(to->value.as_vector, from->value.as_vector)); + break; + + case IGRAPH_ATTRIBUTE_STRING: + IGRAPH_CHECK(igraph_strvector_update(to->value.as_strvector, from->value.as_strvector)); + break; + + case IGRAPH_ATTRIBUTE_BOOLEAN: + IGRAPH_CHECK(igraph_vector_bool_update(to->value.as_vector_bool, from->value.as_vector_bool)); + break; + + case IGRAPH_ATTRIBUTE_UNSPECIFIED: + break; + + default: + break; + } + + return IGRAPH_SUCCESS; +} + +static void igraph_i_attribute_record_destroy_values(igraph_attribute_record_t *attr) { + IGRAPH_ASSERT(attr != NULL); + + if (attr->value.as_raw) { + switch (attr->type) { + case IGRAPH_ATTRIBUTE_NUMERIC: + igraph_vector_destroy(attr->value.as_vector); + break; + + case IGRAPH_ATTRIBUTE_STRING: + igraph_strvector_destroy(attr->value.as_strvector); + break; + + case IGRAPH_ATTRIBUTE_BOOLEAN: + igraph_vector_bool_destroy(attr->value.as_vector_bool); + break; + + default: + break; + } + + igraph_free(attr->value.as_raw); + attr->value.as_raw = NULL; + } + + switch (attr->type) { + case IGRAPH_ATTRIBUTE_NUMERIC: + attr->default_value.numeric = 0; + break; + + case IGRAPH_ATTRIBUTE_STRING: + if (attr->default_value.string) { + igraph_free(attr->default_value.string); + attr->default_value.string = NULL; + } + break; + + case IGRAPH_ATTRIBUTE_BOOLEAN: + attr->default_value.boolean = 0; + break; + + default: + break; + } + + attr->type = IGRAPH_ATTRIBUTE_UNSPECIFIED; +} + +/** + * \function igraph_attribute_record_destroy + * \brief Destroys an attribute record. + * + * \param attr the previously initialized attribute record to destroy. + * + * Time complexity: operating system dependent. + */ +void igraph_attribute_record_destroy(igraph_attribute_record_t *attr) { + igraph_i_attribute_record_destroy_values(attr); + + if (attr->name) { + igraph_free(attr->name); + attr->name = NULL; + } +} + +/** + * \function igraph_attribute_record_check_type + * \brief Checks whether the type of the attribute record is equal to an expected type. + * + * \param attr the attribute record to test + * \param type the expected type of the attribute record + * \return Error code: + * \c IGRAPH_EINVAL if the type of the attribute record is not equal to + * the expected type + * + * Time complexity: O(1). + */ +igraph_error_t igraph_attribute_record_check_type( + const igraph_attribute_record_t *attr, igraph_attribute_type_t type +) { + if (type != attr->type) { + switch (type) { + case IGRAPH_ATTRIBUTE_STRING: + IGRAPH_ERROR("String attribute expected.", IGRAPH_EINVAL); + break; + case IGRAPH_ATTRIBUTE_NUMERIC: + IGRAPH_ERROR("Numeric attribute expected.", IGRAPH_EINVAL); + break; + case IGRAPH_ATTRIBUTE_BOOLEAN: + IGRAPH_ERROR("Boolean attribute expected.", IGRAPH_EINVAL); + break; + case IGRAPH_ATTRIBUTE_OBJECT: + IGRAPH_ERROR("Object attribute expected.", IGRAPH_EINVAL); + break; + default: + IGRAPH_ERROR("Attribute with unknown type expected.", IGRAPH_EINVAL); + break; + } + } + + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_attribute_record_size + * \brief Returns the size of the value vector in an attribute record. + * + * \param attr the attribute record to query + * \return the number of elements in the value vector of the attribute record + */ +igraph_integer_t igraph_attribute_record_size(const igraph_attribute_record_t *attr) { + IGRAPH_ASSERT(attr != NULL); + + switch (attr->type) { + case IGRAPH_ATTRIBUTE_NUMERIC: + return igraph_vector_size(attr->value.as_vector); + + case IGRAPH_ATTRIBUTE_STRING: + return igraph_strvector_size(attr->value.as_strvector); + + case IGRAPH_ATTRIBUTE_BOOLEAN: + return igraph_vector_bool_size(attr->value.as_vector_bool); + + case IGRAPH_ATTRIBUTE_UNSPECIFIED: + return 0; + + default: + IGRAPH_ERRORF("Unsupported attribute type: %d", IGRAPH_EINVAL, (int) attr->type); + } +} + +/** + * \function igraph_attribute_record_resize + * \brief Resizes the value vector in an attribute record. + * + * When the value vector is shorter than the desired length, it + * will be expanded with \c IGRAPH_NAN for numeric vectors, \c false for Boolean + * vectors and empty strings for string vectors. + * + * \param attr the attribute record to update + * \param new_size the new size of the value vector + * \return Error code: + * \c IGRAPH_ENOMEM if there is not enough memory. + * \c IGRAPH_EINVAL if the type of the attribute record is not specified yet. + */ +igraph_error_t igraph_attribute_record_resize( + igraph_attribute_record_t *attr, igraph_integer_t new_size +) { + igraph_integer_t i; + igraph_vector_t *vec; + igraph_vector_bool_t *log; + igraph_strvector_t *str; + + IGRAPH_ASSERT(attr != NULL); + + switch (attr->type) { + + case IGRAPH_ATTRIBUTE_NUMERIC: + vec = attr->value.as_vector; + i = igraph_vector_size(vec); + IGRAPH_CHECK(igraph_vector_resize(vec, new_size)); + while (i < new_size) { + VECTOR(*vec)[i++] = attr->default_value.numeric; + } + break; + + case IGRAPH_ATTRIBUTE_BOOLEAN: + log = attr->value.as_vector_bool; + i = igraph_vector_bool_size(log); + IGRAPH_CHECK(igraph_vector_bool_resize(log, new_size)); + while (i < new_size) { + VECTOR(*log)[i++] = attr->default_value.boolean; + } + break; + + case IGRAPH_ATTRIBUTE_STRING: + str = attr->value.as_strvector; + if (attr->default_value.string == 0 || (*attr->default_value.string == 0)) { + IGRAPH_CHECK(igraph_strvector_resize(str, new_size)); + } else { + i = igraph_strvector_size(str); + IGRAPH_CHECK(igraph_strvector_resize(str, new_size)); + while (i < new_size) { + IGRAPH_CHECK(igraph_strvector_set(str, i++, attr->default_value.string)); + } + } + break; + + case IGRAPH_ATTRIBUTE_UNSPECIFIED: + IGRAPH_ERROR("Attribute record has no type yet.", IGRAPH_EINVAL); + break; + + default: + IGRAPH_ERRORF("Unsupported attribute type: %d", IGRAPH_EINVAL, (int) attr->type); + } + + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_attribute_record_set_default_numeric + * \brief Sets the default value of the attribute to the given number. + * + * + * This function must be called for numeric attribute records only. When not + * specified, the default value of numeric attributes is NaN. + * + * \param attr the attribute record to update + * \param value the new default value + * \return Error code: + * \c IGRAPH_EINVAL if the attribute record has a non-numeric type + */ +igraph_error_t igraph_attribute_record_set_default_numeric( + igraph_attribute_record_t *attr, igraph_real_t value +) { + if (attr->type != IGRAPH_ATTRIBUTE_NUMERIC) { + return IGRAPH_EINVAL; + } + + attr->default_value.numeric = value; + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_attribute_record_set_default_boolean + * \brief Sets the default value of the attribute to the given logical value. + * + * + * This function must be called for Boolean attribute records only. When not + * specified, the default value of Boolean attributes is \c false. + * + * \param attr the attribute record to update + * \param value the new default value + * \return Error code: + * \c IGRAPH_EINVAL if the attribute record is not of Boolean type + */ +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_set_default_boolean( + igraph_attribute_record_t *attr, igraph_bool_t value +) { + if (attr->type != IGRAPH_ATTRIBUTE_BOOLEAN) { + return IGRAPH_EINVAL; + } + + attr->default_value.boolean = value; + return IGRAPH_SUCCESS; +} + +/** + * \function igraph_attribute_record_set_default_string + * \brief Sets the default value of the attribute to the given string. + * + * + * This function must be called for string attribute records only. When not + * specified, the default value of string attributes is an empty string. + * + * \param attr the attribute record to update + * \param value the new default value. \c NULL means an empty string. + * + * \return Error code: + * \c IGRAPH_ENOMEM if there is not enough memory + * \c IGRAPH_EINVAL if the attribute record is not of string type + */ +IGRAPH_EXPORT igraph_error_t igraph_attribute_record_set_default_string( + igraph_attribute_record_t *attr, const char* value +) { + char* copy; + + if (attr->type != IGRAPH_ATTRIBUTE_STRING) { + return IGRAPH_EINVAL; + } + + if (value && (*value != 0)) { + copy = strdup(value); + IGRAPH_CHECK_OOM(copy, "Insufficient memory to duplicate default value."); + } else { + copy = NULL; + } + + if (attr->default_value.string) { + igraph_free(attr->default_value.string); + } + attr->default_value.string = copy; + + return IGRAPH_SUCCESS; +} + + +/** + * \function igraph_attribute_record_set_name + * \brief Sets the attribute name in an attribute record. + * + * \param attr the attribute record to update + * \param name the new name + * \return Error code: + * \c IGRAPH_ENOMEM if there is not enough memory. + */ +igraph_error_t igraph_attribute_record_set_name( + igraph_attribute_record_t *attr, const char* name +) { + char* new_name; + + IGRAPH_ASSERT(attr != NULL); + + if (name != NULL) { + new_name = strdup(name); + IGRAPH_CHECK_OOM(new_name, "Insufficient memory for allocating attribute name."); + } else { + new_name = NULL; + } + + if (attr->name) { + igraph_free(attr->name); + } + + attr->name = new_name; + + return IGRAPH_SUCCESS; +} + +static void igraph_i_attribute_record_set_type( + igraph_attribute_record_t *attr, igraph_attribute_type_t type, void *ptr +) { + bool type_changed = attr->type != type; + + if (type_changed || attr->value.as_raw != ptr) { + igraph_i_attribute_record_destroy_values(attr); + attr->type = type; + attr->value.as_raw = ptr; + } + + if (type_changed && type == IGRAPH_ATTRIBUTE_NUMERIC) { + IGRAPH_ASSERT( + igraph_attribute_record_set_default_numeric(attr, IGRAPH_NAN) == IGRAPH_SUCCESS + ); + } +} + +/** + * \function igraph_attribute_record_set_type + * \brief Sets the type of an attribute record. + * + * + * When the new type being set is different from the old type, any values already + * stored in the attribute record will be destroyed and a new, empty attribute + * value vector will be allocated. When the new type is the same as the old + * type, this function is a no-op. + * + * \param attr the attribute record to update + * \param type the new type + * \return Error code: + * \c IGRAPH_ENOMEM if there is not enough memory. + */ +igraph_error_t igraph_attribute_record_set_type( + igraph_attribute_record_t *attr, igraph_attribute_type_t type +) { + void* ptr; + + IGRAPH_ASSERT(attr != NULL); + + if (attr->type != type) { + switch (type) { + case IGRAPH_ATTRIBUTE_NUMERIC: { + igraph_vector_t* vec = IGRAPH_CALLOC(1, igraph_vector_t); + IGRAPH_CHECK_OOM(vec, "Insufficient memory for attribute record."); + IGRAPH_FINALLY(igraph_free, vec); + IGRAPH_VECTOR_INIT_FINALLY(vec, 0); + ptr = vec; + } + break; + + case IGRAPH_ATTRIBUTE_STRING: { + igraph_strvector_t* strvec = IGRAPH_CALLOC(1, igraph_strvector_t); + IGRAPH_CHECK_OOM(strvec, "Insufficient memory for attribute record."); + IGRAPH_FINALLY(igraph_free, strvec); + IGRAPH_CHECK(igraph_strvector_init(strvec, 0)); + IGRAPH_FINALLY(igraph_strvector_destroy, strvec); + ptr = strvec; + } + break; + + case IGRAPH_ATTRIBUTE_BOOLEAN: { + igraph_vector_bool_t* boolvec = IGRAPH_CALLOC(1, igraph_vector_bool_t); + IGRAPH_CHECK_OOM(boolvec, "Insufficient memory for attribute record."); + IGRAPH_FINALLY(igraph_free, boolvec); + IGRAPH_VECTOR_BOOL_INIT_FINALLY(boolvec, 0); + ptr = boolvec; + } + break; + + default: + IGRAPH_ERRORF("Unsupported attribute type: %d", IGRAPH_EINVAL, (int) type); + } + + igraph_i_attribute_record_set_type(attr, type, ptr); + IGRAPH_FINALLY_CLEAN(2); + } + + return IGRAPH_SUCCESS; +} + +#define ATTRIBUTE_RECORD_LIST +#define BASE_ATTRIBUTE_RECORD +#define CUSTOM_INIT_DESTROY +#include "igraph_pmt.h" +#include "../core/typed_list.pmt" +#include "igraph_pmt_off.h" +#undef CUSTOM_INIT_DESTROY +#undef BASE_ATTRIBUTE_RECORD +#undef ATTRIBUTE_RECORD_LIST + +static igraph_error_t igraph_i_attribute_record_list_init_item( + const igraph_attribute_record_list_t* list, igraph_attribute_record_t* item +) { + return igraph_attribute_record_init(item, NULL, IGRAPH_ATTRIBUTE_UNSPECIFIED); +} + +static igraph_error_t igraph_i_attribute_record_list_copy_item( + igraph_attribute_record_t* dest, const igraph_attribute_record_t* source +) { + return igraph_attribute_record_init_copy(dest, source); +} + +static void igraph_i_attribute_record_list_destroy_item(igraph_attribute_record_t* item) { + igraph_attribute_record_destroy(item); +} + /* Should you ever want to have a thread-local attribute handler table, prepend * IGRAPH_THREAD_LOCAL to the following declaration and #include "config.h". */ igraph_attribute_table_t *igraph_i_attribute_table = NULL; -igraph_error_t igraph_i_attribute_init(igraph_t *graph, void *attr) { +igraph_error_t igraph_i_attribute_init( + igraph_t *graph, const igraph_attribute_record_list_t *attr +) { graph->attr = NULL; if (igraph_i_attribute_table) { - return igraph_i_attribute_table->init(graph, attr); - } else { - return IGRAPH_SUCCESS; + IGRAPH_CHECK(igraph_i_attribute_table->init(graph, attr)); + if (graph->attr == NULL) { + IGRAPH_ERROR("Attribute handler did not initialize attr pointer", IGRAPH_FAILURE); + } } + return IGRAPH_SUCCESS; } void igraph_i_attribute_destroy(igraph_t *graph) { - if (igraph_i_attribute_table) { + if (graph->attr && igraph_i_attribute_table) { igraph_i_attribute_table->destroy(graph); } graph->attr = NULL; @@ -52,15 +633,19 @@ void igraph_i_attribute_destroy(igraph_t *graph) { igraph_error_t igraph_i_attribute_copy(igraph_t *to, const igraph_t *from, igraph_bool_t ga, igraph_bool_t va, igraph_bool_t ea) { - to->attr = NULL; - if (igraph_i_attribute_table) { - return igraph_i_attribute_table->copy(to, from, ga, va, ea); - } else { - return IGRAPH_SUCCESS; + igraph_i_attribute_destroy(to); + if (from->attr && igraph_i_attribute_table) { + IGRAPH_CHECK(igraph_i_attribute_table->copy(to, from, ga, va, ea)); + if (to->attr == NULL) { + IGRAPH_ERROR("Attribute handler did not initialize attr pointer", IGRAPH_FAILURE); + } } + return IGRAPH_SUCCESS; } -igraph_error_t igraph_i_attribute_add_vertices(igraph_t *graph, igraph_integer_t nv, void *attr) { +igraph_error_t igraph_i_attribute_add_vertices( + igraph_t *graph, igraph_integer_t nv, const igraph_attribute_record_list_t *attr +) { if (igraph_i_attribute_table) { return igraph_i_attribute_table->add_vertices(graph, nv, attr); } else { @@ -98,8 +683,10 @@ igraph_error_t igraph_i_attribute_combine_vertices(const igraph_t *graph, } } -igraph_error_t igraph_i_attribute_add_edges(igraph_t *graph, - const igraph_vector_int_t *edges, void *attr) { +igraph_error_t igraph_i_attribute_add_edges( + igraph_t *graph, const igraph_vector_int_t *edges, + const igraph_attribute_record_list_t *attr +) { if (igraph_i_attribute_table) { return igraph_i_attribute_table->add_edges(graph, edges, attr); } else { @@ -163,7 +750,7 @@ igraph_bool_t igraph_i_attribute_has_attr(const igraph_t *graph, } } -igraph_error_t igraph_i_attribute_gettype(const igraph_t *graph, +igraph_error_t igraph_i_attribute_get_type(const igraph_t *graph, igraph_attribute_type_t *type, igraph_attribute_elemtype_t elemtype, const char *name) { diff --git a/src/vendor/cigraph/src/graph/attributes.h b/src/vendor/cigraph/src/graph/attributes.h index c1ceb3e7a0f..2e8a344f965 100644 --- a/src/vendor/cigraph/src/graph/attributes.h +++ b/src/vendor/cigraph/src/graph/attributes.h @@ -26,24 +26,18 @@ __BEGIN_DECLS -#define IGRAPH_I_ATTRIBUTE_DESTROY(graph) \ - do {if ((graph)->attr) igraph_i_attribute_destroy(graph);} while(0) -#define IGRAPH_I_ATTRIBUTE_COPY(to,from,ga,va,ea) do { \ - igraph_error_t igraph_i_ret2=IGRAPH_SUCCESS; \ - (to)->attr = NULL; \ - if ((from)->attr) { \ - IGRAPH_CHECK(igraph_i_ret2=igraph_i_attribute_copy((to),(from),(ga),(va),(ea))); \ - } \ - if (igraph_i_ret2 != IGRAPH_SUCCESS) { \ - IGRAPH_ERROR("", igraph_i_ret2); \ - } \ - } while(0) - -igraph_error_t igraph_i_attribute_init(igraph_t *graph, void *attr); +igraph_error_t igraph_i_attribute_init( + igraph_t *graph, const igraph_attribute_record_list_t *attr +); void igraph_i_attribute_destroy(igraph_t *graph); -igraph_error_t igraph_i_attribute_copy(igraph_t *to, const igraph_t *from, - igraph_bool_t ga, igraph_bool_t va, igraph_bool_t ea); -igraph_error_t igraph_i_attribute_add_vertices(igraph_t *graph, igraph_integer_t nv, void *attr); +igraph_error_t igraph_i_attribute_copy( + igraph_t *to, const igraph_t *from, + igraph_bool_t ga, igraph_bool_t va, igraph_bool_t ea +); +igraph_error_t igraph_i_attribute_add_vertices( + igraph_t *graph, igraph_integer_t nv, + const igraph_attribute_record_list_t *attr +); igraph_error_t igraph_i_attribute_permute_vertices(const igraph_t *graph, igraph_t *newgraph, const igraph_vector_int_t *idx); @@ -51,8 +45,10 @@ igraph_error_t igraph_i_attribute_combine_vertices(const igraph_t *graph, igraph_t *newgraph, const igraph_vector_int_list_t *merges, const igraph_attribute_combination_t *comb); -igraph_error_t igraph_i_attribute_add_edges(igraph_t *graph, - const igraph_vector_int_t *edges, void *attr); +igraph_error_t igraph_i_attribute_add_edges( + igraph_t *graph, const igraph_vector_int_t *edges, + const igraph_attribute_record_list_t *attr +); igraph_error_t igraph_i_attribute_permute_edges(const igraph_t *graph, igraph_t *newgraph, const igraph_vector_int_t *idx); @@ -71,7 +67,7 @@ igraph_error_t igraph_i_attribute_get_info(const igraph_t *graph, igraph_bool_t igraph_i_attribute_has_attr(const igraph_t *graph, igraph_attribute_elemtype_t type, const char *name); -igraph_error_t igraph_i_attribute_gettype(const igraph_t *graph, +igraph_error_t igraph_i_attribute_get_type(const igraph_t *graph, igraph_attribute_type_t *type, igraph_attribute_elemtype_t elemtype, const char *name); diff --git a/src/vendor/cigraph/src/graph/caching.c b/src/vendor/cigraph/src/graph/caching.c index 2f9781c44eb..b2741710cb5 100644 --- a/src/vendor/cigraph/src/graph/caching.c +++ b/src/vendor/cigraph/src/graph/caching.c @@ -17,6 +17,7 @@ */ #include "igraph_interface.h" +#include "igraph_misc.h" /* IGRAPH_STATIC_ASSERT */ #include "graph/caching.h" diff --git a/src/vendor/cigraph/src/graph/cattributes.c b/src/vendor/cigraph/src/graph/cattributes.c index 21bf872c67a..0a2ae020557 100644 --- a/src/vendor/cigraph/src/graph/cattributes.c +++ b/src/vendor/cigraph/src/graph/cattributes.c @@ -9,7 +9,6 @@ the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -32,185 +31,189 @@ /* An attribute is either a numeric vector (vector_t), a boolean vector * (vector_bool_t) or a string vector (strvector_t). - * The attribute itself is stored in a struct igraph_attribute_record_t. - * There is one such object for each attribute. The igraph_t has a pointer - * to an igraph_i_cattribute_t, which contains three vector_ptr_t's, each - * holding pointers to igraph_attribute_record_t objects. */ + * The attribute itself is stored in a struct igraph_attribute_record_t. There + * is one such object for each attribute. The igraph_t has a pointer to an + * igraph_i_cattribute_t, which contains three igraph_attribute_vector_list_t's, + * each holding pointers to igraph_attribute_record_t objects. */ -/* This function is used for producing better error messages. */ -static const char *attribute_type_name(igraph_attribute_type_t type) { - switch (type) { - case IGRAPH_ATTRIBUTE_UNSPECIFIED: - return "unspecified"; /* TODO: should probably trigger a fatal error */ - case IGRAPH_ATTRIBUTE_NUMERIC: - return "numeric"; - case IGRAPH_ATTRIBUTE_BOOLEAN: - return "boolean"; - case IGRAPH_ATTRIBUTE_STRING: - return "string"; - case IGRAPH_ATTRIBUTE_OBJECT: - return "object"; +typedef struct igraph_i_cattributes_t { + igraph_attribute_record_list_t gal; + igraph_attribute_record_list_t val; + igraph_attribute_record_list_t eal; +} igraph_i_cattributes_t; + +/* + * Finds an attribute with the given name in an attribute record list, and + * returns the index of the record in the list, or -1 if there was no such + * attribute. + */ +static igraph_integer_t igraph_i_cattribute_find_index( + const igraph_attribute_record_list_t *attrs, const char *name +) { + igraph_integer_t i, n = igraph_attribute_record_list_size(attrs); + for (i = 0; i < n; i++) { + igraph_attribute_record_t *rec = igraph_attribute_record_list_get_ptr(attrs, i); + if (!strcmp(rec->name, name)) { + return i; + } } - /* The following line is intentionally not in a default switch label - * so that the compiler can warn about unhandled enum values, - * should additional attribute types ever be added in the future. */ - IGRAPH_FATALF("Invalid attribute type %d found.", (int) type); + return -1; } -static igraph_bool_t igraph_i_cattribute_find(const igraph_vector_ptr_t *ptrvec, - const char *name, igraph_integer_t *idx) { - igraph_integer_t i, n = igraph_vector_ptr_size(ptrvec); - igraph_bool_t l = false; - for (i = 0; !l && i < n; i++) { - igraph_attribute_record_t *rec = VECTOR(*ptrvec)[i]; - l = !strcmp(rec->name, name); - } - if (idx) { - *idx = i - 1; +/* + * Finds an attribute with the given name in an attribute record list, and + * returns the attribute record or NULL if there was no such attribute. + * Optionally, the type of the attribute can be enforced; use + * IGRAPH_ATTRIBUTE_UNSPECIFIED if you do not care about the type. + */ +static igraph_attribute_record_t* igraph_i_cattribute_find( + igraph_attribute_record_list_t *attrs, const char *name, + igraph_attribute_type_t type +) { + igraph_integer_t index = igraph_i_cattribute_find_index(attrs, name); + igraph_attribute_record_t *rec; + + if (index >= 0) { + rec = igraph_attribute_record_list_get_ptr(attrs, index); + if (type == IGRAPH_ATTRIBUTE_UNSPECIFIED || type == rec->type) { + return rec; + } } - return l; + + return NULL; } /* - * Restores attribute vector lengths to their original size after a failure. - * This function assumes that none of the attribute vectors are shorter than origlen. - * Some may be longer due to a partially completed size extension: these will be - * shrunk to their original size. + * Same as igraph_i_cattribute_find(), but suitable for const attribute record + * lists. */ -static void igraph_i_cattribute_revert_attribute_vector_sizes( - igraph_vector_ptr_t *attrlist, igraph_integer_t origlen) { +static const igraph_attribute_record_t* igraph_i_cattribute_find_const( + const igraph_attribute_record_list_t *attrs, const char *name, + igraph_attribute_type_t type +) { + igraph_integer_t index = igraph_i_cattribute_find_index(attrs, name); + igraph_attribute_record_t *rec; - igraph_integer_t no_of_attrs = igraph_vector_ptr_size(attrlist); - for (igraph_integer_t i = 0; i < no_of_attrs; i++) { - igraph_attribute_record_t *rec = VECTOR(*attrlist)[i]; - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *nvec = (igraph_vector_t *) rec->value; - IGRAPH_ASSERT(igraph_vector_capacity(nvec) >= origlen); - igraph_vector_resize(nvec, origlen); /* shrinks */ - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *bvec = (igraph_vector_bool_t *) rec->value; - IGRAPH_ASSERT(igraph_vector_bool_capacity(bvec) >= origlen); - igraph_vector_bool_resize(bvec, origlen); /* shrinks */ - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *svec = (igraph_strvector_t *) rec->value; - IGRAPH_ASSERT(igraph_strvector_capacity(svec) >= origlen); - igraph_strvector_resize(svec, origlen); /* shrinks */ - } else { - /* Must never reach here */ - IGRAPH_FATAL("Unknown attribute type encountered."); + if (index >= 0) { + rec = igraph_attribute_record_list_get_ptr(attrs, index); + if (type == IGRAPH_ATTRIBUTE_UNSPECIFIED || type == rec->type) { + return rec; } } + + return NULL; } -typedef struct igraph_i_cattributes_t { - igraph_vector_ptr_t gal; - igraph_vector_ptr_t val; - igraph_vector_ptr_t eal; -} igraph_i_cattributes_t; +/* + * Finds an attribute with the given name in an attribute record list, and + * returns the attribute record in an output argument. Returns an error code + * if there is no such attribute. Optionally, the type of the attribute can be + * enforced; use IGRAPH_ATTRIBUTE_UNSPECIFIED if you do not care about the type. + */ +static igraph_error_t igraph_i_cattribute_find_or_return( + igraph_attribute_record_list_t *attrs, const char *name, + igraph_attribute_type_t type, igraph_attribute_record_t **ptr +) { + igraph_attribute_record_t *rec; -static igraph_error_t igraph_i_cattributes_copy_attribute_record(igraph_attribute_record_t **newrec, - const igraph_attribute_record_t *rec) { - igraph_vector_t *num, *newnum; - igraph_strvector_t *str, *newstr; + rec = igraph_i_cattribute_find(attrs, name, IGRAPH_ATTRIBUTE_UNSPECIFIED); + if (!rec) { + IGRAPH_ERRORF("Attribute '%s' does not exist.", IGRAPH_EINVAL, name); + } - *newrec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - if (!(*newrec)) { - IGRAPH_ERROR("Cannot copy attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ + if (type != IGRAPH_ATTRIBUTE_UNSPECIFIED) { + IGRAPH_CHECK(igraph_attribute_record_check_type(rec, type)); } - IGRAPH_FINALLY(igraph_free, *newrec); - (*newrec)->type = rec->type; - (*newrec)->name = strdup(rec->name); - if (!(*newrec)->name) { - IGRAPH_ERROR("Cannot copy attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ + + if (ptr) { + *ptr = rec; } - IGRAPH_FINALLY(igraph_free, (void*)(*newrec)->name); - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - num = (igraph_vector_t *)rec->value; - newnum = IGRAPH_CALLOC(1, igraph_vector_t); - if (!newnum) { - IGRAPH_ERROR("Cannot copy attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newnum); - IGRAPH_CHECK(igraph_vector_init_copy(newnum, num)); - IGRAPH_FINALLY(igraph_vector_destroy, newnum); - (*newrec)->value = newnum; - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - str = (igraph_strvector_t*)rec->value; - newstr = IGRAPH_CALLOC(1, igraph_strvector_t); - if (!newstr) { - IGRAPH_ERROR("Cannot copy attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newstr); - IGRAPH_CHECK(igraph_strvector_init_copy(newstr, str)); - IGRAPH_FINALLY(igraph_strvector_destroy, newstr); - (*newrec)->value = newstr; - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *log = (igraph_vector_bool_t*) rec->value; - igraph_vector_bool_t *newlog = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (!newlog) { - IGRAPH_ERROR("Cannot copy attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ + + return IGRAPH_SUCCESS; +} + +/* + * Finds an attribute with the given name in an attribute record list, and + * returns the attribute record in an output argument. Creates a new attribute + * with the given name if there is no such attribute. The type of the attribute + * needs to be specified so we can create the appropriate value vector if needed. + * You can specify a length; when the existing value vector for the attribute + * is shorter than this length, it will be extended to ensure that it has at + * least this many elements. You can pass 0 as the length if you do not want to + * expand value vectors. + */ +static igraph_error_t igraph_i_cattribute_find_or_create( + igraph_attribute_record_list_t *attrs, + const char *name, igraph_attribute_type_t type, + igraph_integer_t length, + igraph_attribute_record_t **ptr +) { + igraph_attribute_record_t *rec; + + rec = igraph_i_cattribute_find(attrs, name, IGRAPH_ATTRIBUTE_UNSPECIFIED); + if (rec) { + if (type != IGRAPH_ATTRIBUTE_UNSPECIFIED) { + IGRAPH_CHECK(igraph_attribute_record_check_type(rec, type)); } - IGRAPH_FINALLY(igraph_free, newlog); - IGRAPH_CHECK(igraph_vector_bool_init_copy(newlog, log)); - IGRAPH_FINALLY(igraph_vector_bool_destroy, newlog); - (*newrec)->value = newlog; + } else { + IGRAPH_CHECK(igraph_attribute_record_list_push_back_new(attrs, &rec)); + IGRAPH_CHECK(igraph_attribute_record_set_name(rec, name)); + IGRAPH_CHECK(igraph_attribute_record_set_type(rec, type)); + } + + if (length > 0 && igraph_attribute_record_size(rec) < length) { + IGRAPH_CHECK(igraph_attribute_record_resize(rec, length)); + } + + if (ptr) { + *ptr = rec; } - IGRAPH_FINALLY_CLEAN(4); return IGRAPH_SUCCESS; } -static void igraph_i_attribute_list_destroy(igraph_vector_ptr_t *attrlist) { - igraph_integer_t i; - igraph_integer_t n = igraph_vector_ptr_size(attrlist); - for (i = 0; i < n; i++) { - igraph_attribute_record_t *rec = VECTOR(*attrlist)[i]; - if (rec) { - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *num = (igraph_vector_t *) rec->value; - igraph_vector_destroy(num); - IGRAPH_FREE(num); - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *str = (igraph_strvector_t *) rec->value; - igraph_strvector_destroy(str); - IGRAPH_FREE(str); - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *boolvec = (igraph_vector_bool_t *) rec->value; - igraph_vector_bool_destroy(boolvec); - IGRAPH_FREE(boolvec); - } - IGRAPH_FREE(rec->name); - IGRAPH_FREE(rec); +/* + * Restores attribute vector lengths to their original size after a failure. + * This function assumes that none of the attribute vectors are shorter than origlen. + * Some may be longer due to a partially completed size extension: these will be + * shrunk to their original size. + */ +static void igraph_i_cattribute_revert_attribute_vector_sizes( + igraph_attribute_record_list_t *attrlist, igraph_integer_t origlen) { + + igraph_integer_t no_of_attrs = igraph_attribute_record_list_size(attrlist); + for (igraph_integer_t i = 0; i < no_of_attrs; i++) { + igraph_attribute_record_t *rec = igraph_attribute_record_list_get_ptr(attrlist, i); + IGRAPH_ASSERT(igraph_attribute_record_size(rec) >= origlen); + if (igraph_attribute_record_resize(rec, origlen) != IGRAPH_SUCCESS) { + /* We should have succeeded for known attribute types because we + * always shrink the vector so throw a fatal error if this happens */ + IGRAPH_FATAL("Unknown attribute type encountered."); } } - igraph_vector_ptr_destroy(attrlist); } -static igraph_error_t igraph_i_cattribute_init(igraph_t *graph, igraph_vector_ptr_t *attr) { - igraph_attribute_record_t *attr_rec; - igraph_integer_t i, n; +static igraph_error_t igraph_i_cattribute_init( + igraph_t *graph, const igraph_attribute_record_list_t *attr +) { igraph_i_cattributes_t *nattr; - n = attr ? igraph_vector_ptr_size(attr) : 0; - nattr = IGRAPH_CALLOC(1, igraph_i_cattributes_t); - if (!nattr) { - IGRAPH_ERROR("Can't init attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } + IGRAPH_CHECK_OOM(nattr, "Insufficient memory to allocate attribute storage."); IGRAPH_FINALLY(igraph_free, nattr); - IGRAPH_CHECK(igraph_vector_ptr_init(&nattr->gal, n)); - IGRAPH_FINALLY(igraph_i_attribute_list_destroy, &nattr->gal); - IGRAPH_CHECK(igraph_vector_ptr_init(&nattr->val, 0)); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &nattr->val); - IGRAPH_CHECK(igraph_vector_ptr_init(&nattr->eal, 0)); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &nattr->eal); - - for (i = 0; i < n; i++) { - IGRAPH_CHECK(igraph_i_cattributes_copy_attribute_record( - &attr_rec, VECTOR(*attr)[i])); - VECTOR(nattr->gal)[i] = attr_rec; + if (attr) { + IGRAPH_CHECK(igraph_attribute_record_list_init_copy(&nattr->gal, attr)); + } else { + IGRAPH_CHECK(igraph_attribute_record_list_init(&nattr->gal, 0)); } + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &nattr->gal); + + IGRAPH_CHECK(igraph_attribute_record_list_init(&nattr->val, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &nattr->val); + + IGRAPH_CHECK(igraph_attribute_record_list_init(&nattr->eal, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &nattr->eal); graph->attr = nattr; IGRAPH_FINALLY_CLEAN(4); @@ -220,260 +223,135 @@ static igraph_error_t igraph_i_cattribute_init(igraph_t *graph, igraph_vector_pt static void igraph_i_cattribute_destroy(igraph_t *graph) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *als[3] = { &attr->gal, &attr->val, &attr->eal }; - for (size_t a = 0; a < 3; a++) { - igraph_i_attribute_list_destroy(als[a]); - } + igraph_attribute_record_list_destroy(&attr->eal); + igraph_attribute_record_list_destroy(&attr->val); + igraph_attribute_record_list_destroy(&attr->gal); IGRAPH_FREE(graph->attr); /* sets to NULL */ } -/* Almost the same as destroy, but we might have null pointers */ - -static void igraph_i_cattribute_copy_free(igraph_i_cattributes_t *attr) { - igraph_vector_ptr_t *als[3] = { &attr->gal, &attr->val, &attr->eal }; - igraph_integer_t i, n; - igraph_vector_t *num; - igraph_strvector_t *str; - igraph_vector_bool_t *boolvec; - igraph_attribute_record_t *rec; - for (size_t a = 0; a < 3; a++) { - n = igraph_vector_ptr_size(als[a]); - for (i = 0; i < n; i++) { - rec = VECTOR(*als[a])[i]; - if (!rec) { - continue; - } - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - num = (igraph_vector_t*)rec->value; - igraph_vector_destroy(num); - IGRAPH_FREE(num); - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - boolvec = (igraph_vector_bool_t*)rec->value; - igraph_vector_bool_destroy(boolvec); - IGRAPH_FREE(boolvec); - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - str = (igraph_strvector_t*)rec->value; - igraph_strvector_destroy(str); - IGRAPH_FREE(str); - } - IGRAPH_FREE(rec->name); - IGRAPH_FREE(rec); - } - } -} - /* No reference counting here. If you use attributes in C you should know what you're doing. */ -static igraph_error_t igraph_i_cattribute_copy(igraph_t *to, const igraph_t *from, - igraph_bool_t ga, igraph_bool_t va, igraph_bool_t ea) { - igraph_i_cattributes_t *attrfrom = from->attr, *attrto; - igraph_vector_ptr_t *alto[3], *alfrom[3] = { &attrfrom->gal, &attrfrom->val, - &attrfrom->eal - }; - igraph_integer_t i, n; +static igraph_error_t igraph_i_cattribute_copy( + igraph_t *to, const igraph_t *from, + igraph_bool_t ga, igraph_bool_t va, igraph_bool_t ea +) { + igraph_i_cattributes_t *attrto, *attrfrom = from->attr; + igraph_attribute_record_list_t *alto[3], *alfrom[3] = { + &attrfrom->gal, &attrfrom->val, &attrfrom->eal + }; + igraph_integer_t i; igraph_bool_t copy[3] = { ga, va, ea }; - to->attr = attrto = IGRAPH_CALLOC(1, igraph_i_cattributes_t); - if (!attrto) { - IGRAPH_ERROR("Cannot copy attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } + + attrto = IGRAPH_CALLOC(1, igraph_i_cattributes_t); + IGRAPH_CHECK_OOM(attrto, "Insufficient memory to copy attributes."); IGRAPH_FINALLY(igraph_free, attrto); - IGRAPH_VECTOR_PTR_INIT_FINALLY(&attrto->gal, 0); - IGRAPH_VECTOR_PTR_INIT_FINALLY(&attrto->val, 0); - IGRAPH_VECTOR_PTR_INIT_FINALLY(&attrto->eal, 0); - IGRAPH_FINALLY_CLEAN(3); - IGRAPH_FINALLY(igraph_i_cattribute_copy_free, attrto); - - alto[0] = &attrto->gal; alto[1] = &attrto->val; alto[2] = &attrto->eal; - for (size_t a = 0; a < 3; a++) { - if (copy[a]) { - n = igraph_vector_ptr_size(alfrom[a]); - IGRAPH_CHECK(igraph_vector_ptr_resize(alto[a], n)); - igraph_vector_ptr_null(alto[a]); - for (i = 0; i < n; i++) { - igraph_attribute_record_t *newrec; - IGRAPH_CHECK(igraph_i_cattributes_copy_attribute_record(&newrec, - VECTOR(*alfrom[a])[i])); - VECTOR(*alto[a])[i] = newrec; - } + + alto[0] = &attrto->gal; + alto[1] = &attrto->val; + alto[2] = &attrto->eal; + + for (i = 0; i < 3; i++) { + if (copy[i]) { + IGRAPH_CHECK(igraph_attribute_record_list_init_copy(alto[i], alfrom[i])); + } else { + IGRAPH_CHECK(igraph_attribute_record_list_init(alto[i], 0)); } + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, alto[i]); } - IGRAPH_FINALLY_CLEAN(2); + to->attr = attrto; + IGRAPH_FINALLY_CLEAN(4); + return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattribute_add_vertices_inner(igraph_t *graph, igraph_integer_t nv, - igraph_vector_ptr_t *nattr) { +static igraph_error_t igraph_i_cattribute_add_vertices_or_edges_inner( + igraph_attribute_record_list_t *val, + igraph_integer_t newlen, igraph_integer_t nv, + const igraph_attribute_record_list_t *nattr +) { + igraph_integer_t length; + igraph_integer_t nattrno = nattr == NULL ? 0 : igraph_attribute_record_list_size(nattr); + igraph_integer_t origlen = newlen - nv; + igraph_integer_t i; + + IGRAPH_ASSERT(origlen >= 0); - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t length = igraph_vector_ptr_size(val); - igraph_integer_t nattrno = nattr == NULL ? 0 : igraph_vector_ptr_size(nattr); - igraph_integer_t origlen = igraph_vcount(graph) - nv; - igraph_integer_t newattrs = 0, i; - igraph_vector_int_t news; - - /* First add the new attributes if any */ - newattrs = 0; - IGRAPH_VECTOR_INT_INIT_FINALLY(&news, 0); + /* Find all the attributes that are newly added, and create new value vectors + * for them in the original graph */ for (i = 0; i < nattrno; i++) { - igraph_attribute_record_t *nattr_entry = VECTOR(*nattr)[i]; + igraph_attribute_record_t *nattr_entry = igraph_attribute_record_list_get_ptr(nattr, i); const char *nname = nattr_entry->name; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(val, nname, &j); - if (!l) { - newattrs++; - IGRAPH_CHECK(igraph_vector_int_push_back(&news, i)); - } else { - /* check types */ - if (nattr_entry->type != - ((igraph_attribute_record_t*)VECTOR(*val)[j])->type) { - IGRAPH_ERROR("You cannot mix attribute types", IGRAPH_EINVAL); - } - } - } - - /* Add NA/empty string vectors for the existing vertices */ - if (newattrs != 0) { - for (i = 0; i < newattrs; i++) { - igraph_attribute_record_t *tmp = VECTOR(*nattr)[VECTOR(news)[i]]; - igraph_attribute_record_t *newrec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_attribute_type_t type = tmp->type; - if (!newrec) { - IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newrec); - newrec->type = type; - newrec->name = strdup(tmp->name); - if (!newrec->name) { - IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)newrec->name); - if (type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *newnum = IGRAPH_CALLOC(1, igraph_vector_t); - if (!newnum) { - IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newnum); - IGRAPH_VECTOR_INIT_FINALLY(newnum, origlen); - newrec->value = newnum; - igraph_vector_fill(newnum, IGRAPH_NAN); - } else if (type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *newstr = IGRAPH_CALLOC(1, igraph_strvector_t); - if (!newstr) { - IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newstr); - IGRAPH_STRVECTOR_INIT_FINALLY(newstr, origlen); - newrec->value = newstr; - } else if (type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *newbool = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (!newbool) { - IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newbool); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newbool, origlen); - newrec->value = newbool; - igraph_vector_bool_fill(newbool, false); - } - IGRAPH_CHECK(igraph_vector_ptr_push_back(val, newrec)); - IGRAPH_FINALLY_CLEAN(4); - } - length = igraph_vector_ptr_size(val); + IGRAPH_CHECK(igraph_i_cattribute_find_or_create(val, nname, nattr_entry->type, origlen, NULL)); } /* Now append the new values */ + length = igraph_attribute_record_list_size(val); for (i = 0; i < length; i++) { - igraph_attribute_record_t *oldrec = VECTOR(*val)[i]; - igraph_attribute_record_t *newrec = 0; - const char *name = oldrec->name; - igraph_integer_t j = -1; - igraph_bool_t l = false; - if (nattr) { - l = igraph_i_cattribute_find(nattr, name, &j); - } - if (l) { + igraph_attribute_record_t *oldrec = igraph_attribute_record_list_get_ptr(val, i); + const igraph_attribute_record_t *newrec = nattr + ? igraph_i_cattribute_find_const(nattr, oldrec->name, oldrec->type) + : NULL; + + IGRAPH_ASSERT(igraph_attribute_record_size(oldrec) == origlen); + + if (newrec) { /* This attribute is present in nattr */ - igraph_vector_t *oldnum, *newnum; - igraph_strvector_t *oldstr, *newstr; - igraph_vector_bool_t *oldbool, *newbool; - newrec = VECTOR(*nattr)[j]; - oldnum = (igraph_vector_t*)oldrec->value; - newnum = (igraph_vector_t*)newrec->value; - oldstr = (igraph_strvector_t*)oldrec->value; - newstr = (igraph_strvector_t*)newrec->value; - oldbool = (igraph_vector_bool_t*)oldrec->value; - newbool = (igraph_vector_bool_t*)newrec->value; - if (oldrec->type != newrec->type) { - IGRAPH_ERROR("Attribute types do not match.", IGRAPH_EINVAL); - } switch (oldrec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: - if (nv != igraph_vector_size(newnum)) { + if (nv != igraph_vector_size(newrec->value.as_vector)) { IGRAPH_ERROR("Invalid numeric attribute length.", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_vector_append(oldnum, newnum)); + IGRAPH_CHECK(igraph_vector_append( + oldrec->value.as_vector, newrec->value.as_vector + )); break; case IGRAPH_ATTRIBUTE_STRING: - if (nv != igraph_strvector_size(newstr)) { + if (nv != igraph_strvector_size(newrec->value.as_strvector)) { IGRAPH_ERROR("Invalid string attribute length.", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_strvector_append(oldstr, newstr)); + IGRAPH_CHECK(igraph_strvector_append( + oldrec->value.as_strvector, newrec->value.as_strvector + )); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - if (nv != igraph_vector_bool_size(newbool)) { + if (nv != igraph_vector_bool_size(newrec->value.as_vector_bool)) { IGRAPH_ERROR("Invalid boolean attribute length.", IGRAPH_EINVAL); } - IGRAPH_CHECK(igraph_vector_bool_append(oldbool, newbool)); + IGRAPH_CHECK(igraph_vector_bool_append( + oldrec->value.as_vector_bool, newrec->value.as_vector_bool + )); break; default: - IGRAPH_WARNING("Invalid attribute type."); + IGRAPH_WARNINGF( + "Attribute '%s' with unknown type %d ignored", + oldrec->name, (int) oldrec->type + ); break; } } else { - /* No such attribute, append NA's */ - igraph_vector_t *oldnum = (igraph_vector_t *)oldrec->value; - igraph_strvector_t *oldstr = (igraph_strvector_t*)oldrec->value; - igraph_vector_bool_t *oldbool = (igraph_vector_bool_t*)oldrec->value; - switch (oldrec->type) { - case IGRAPH_ATTRIBUTE_NUMERIC: - IGRAPH_CHECK(igraph_vector_resize(oldnum, origlen + nv)); - for (j = origlen; j < origlen + nv; j++) { - VECTOR(*oldnum)[j] = IGRAPH_NAN; - } - break; - case IGRAPH_ATTRIBUTE_STRING: - IGRAPH_CHECK(igraph_strvector_resize(oldstr, origlen + nv)); - break; - case IGRAPH_ATTRIBUTE_BOOLEAN: - IGRAPH_CHECK(igraph_vector_bool_resize(oldbool, origlen + nv)); - for (j = origlen; j < origlen + nv; j++) { - VECTOR(*oldbool)[j] = 0; - } - break; - default: - IGRAPH_WARNING("Invalid attribute type"); - break; - } + /* No such attribute among the new ones so just extend the length + * of the current record */ + IGRAPH_CHECK(igraph_attribute_record_resize(oldrec, newlen)); } - } - igraph_vector_int_destroy(&news); - IGRAPH_FINALLY_CLEAN(1); + IGRAPH_ASSERT(igraph_attribute_record_size(oldrec) == newlen); + } return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattribute_add_vertices(igraph_t *graph, igraph_integer_t nv, - igraph_vector_ptr_t *nattr) { - /* Record information needed to restore attribute vector sizes */ - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t origlen = igraph_vcount(graph) - nv; +static igraph_error_t igraph_i_cattribute_add_vertices_or_edges( + igraph_attribute_record_list_t *val, + igraph_integer_t newlen, igraph_integer_t nv, + const igraph_attribute_record_list_t *nattr +) { + igraph_integer_t origlen = newlen - nv; + igraph_error_t err = igraph_i_cattribute_add_vertices_or_edges_inner( + val, newlen, nv, nattr + ); - /* Attempt adding attributes */ - igraph_error_t err = igraph_i_cattribute_add_vertices_inner(graph, nv, nattr); if (err != IGRAPH_SUCCESS) { /* If unsuccessful, revert attribute vector sizes. * The following function assumes that all attributes vectors that @@ -490,30 +368,16 @@ static igraph_error_t igraph_i_cattribute_add_vertices(igraph_t *graph, igraph_i */ igraph_i_cattribute_revert_attribute_vector_sizes(val, origlen); } + return err; } -static void igraph_i_cattribute_clear_attribute_container(igraph_vector_ptr_t *v) { - igraph_integer_t i, n = igraph_vector_ptr_size(v); - for (i = 0; i < n; i++) { - igraph_attribute_record_t *rec = VECTOR(*v)[i]; - IGRAPH_FREE(rec->name); - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *numv = (igraph_vector_t*) rec->value; - igraph_vector_destroy(numv); - IGRAPH_FREE(numv); - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *strv = (igraph_strvector_t*) rec->value; - igraph_strvector_destroy(strv); - IGRAPH_FREE(strv); - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *boolv = (igraph_vector_bool_t*) rec->value; - igraph_vector_bool_destroy(boolv); - IGRAPH_FREE(boolv); - } - IGRAPH_FREE(rec); - } - igraph_vector_ptr_clear(v); +static igraph_error_t igraph_i_cattribute_add_vertices( + igraph_t *graph, igraph_integer_t nv, + const igraph_attribute_record_list_t *nattr +) { + igraph_i_cattributes_t *attr = graph->attr; + return igraph_i_cattribute_add_vertices_or_edges(&attr->val, igraph_vcount(graph), nv, nattr); } typedef struct { @@ -631,12 +495,65 @@ static igraph_error_t igraph_i_attribute_permutation_work_area_permute_and_store return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattribute_permute_vertices_in_place( - igraph_t *graph, const igraph_vector_int_t *idx +static igraph_error_t igraph_i_cattribute_permute_attribute_record_list( + igraph_attribute_record_list_t *attrs, + igraph_attribute_record_list_t *new_attrs, + const igraph_vector_int_t *idx ) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t valno = igraph_vector_ptr_size(val); + igraph_integer_t i, no_attrs, idxlen; + + no_attrs = igraph_attribute_record_list_size(attrs); + + /* When vertices or edges are permuted, we now assume that there are no + * attributes in the target attribute list yet */ + IGRAPH_ASSERT(igraph_attribute_record_list_empty(new_attrs)); + IGRAPH_FINALLY(igraph_attribute_record_list_clear, new_attrs); + + idxlen = igraph_vector_int_size(idx); + for (i = 0; i < no_attrs; i++) { + igraph_attribute_record_t *oldrec = igraph_attribute_record_list_get_ptr(attrs, i); + igraph_attribute_type_t type = oldrec->type; + + /* Create a record for the same attribute in the new graph */ + igraph_attribute_record_t *newrec; + IGRAPH_CHECK(igraph_i_cattribute_find_or_create( + new_attrs, oldrec->name, oldrec->type, idxlen, &newrec + )); + + /* The data */ + switch (type) { + case IGRAPH_ATTRIBUTE_NUMERIC: + IGRAPH_CHECK(igraph_vector_index( + oldrec->value.as_vector, newrec->value.as_vector, idx + )); + break; + case IGRAPH_ATTRIBUTE_BOOLEAN: + IGRAPH_CHECK(igraph_vector_bool_index( + oldrec->value.as_vector_bool, newrec->value.as_vector_bool, idx + )); + break; + case IGRAPH_ATTRIBUTE_STRING: + IGRAPH_CHECK(igraph_strvector_index( + oldrec->value.as_strvector, newrec->value.as_strvector, idx + )); + break; + default: + IGRAPH_WARNINGF( + "Attribute '%s' with unknown type %d ignored", + oldrec->name, (int) oldrec->type + ); + } + } + + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + +static igraph_error_t igraph_i_cattribute_permute_attribute_record_list_in_place( + igraph_attribute_record_list_t *attrs, const igraph_vector_int_t *idx +) { + igraph_integer_t no_attrs = igraph_attribute_record_list_size(attrs); igraph_integer_t i, j; igraph_attribute_record_t *oldrec; igraph_vector_t *num, *num_work; @@ -646,7 +563,7 @@ static igraph_error_t igraph_i_cattribute_permute_vertices_in_place( igraph_integer_t idx_size = igraph_vector_int_size(idx); /* shortcut: don't allocate anything if there are no attributes */ - if (valno == 0) { + if (no_attrs == 0) { return IGRAPH_SUCCESS; } @@ -655,29 +572,32 @@ static igraph_error_t igraph_i_cattribute_permute_vertices_in_place( * back out from a permutation once we've started it */ IGRAPH_CHECK(igraph_i_attribute_permutation_work_area_init(&work_area, idx_size)); IGRAPH_FINALLY(igraph_i_attribute_permutation_work_area_destroy, &work_area); - for (i = 0; i < valno; i++) { - oldrec = VECTOR(*val)[i]; + for (i = 0; i < no_attrs; i++) { + oldrec = igraph_attribute_record_list_get_ptr(attrs, i); switch (oldrec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: - num = (igraph_vector_t*) oldrec->value; + num = oldrec->value.as_vector; IGRAPH_CHECK(igraph_vector_reserve(num, idx_size)); IGRAPH_CHECK(igraph_i_attribute_permutation_work_area_alloc_for_numeric(&work_area)); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - oldbool = (igraph_vector_bool_t*) oldrec->value; + oldbool = oldrec->value.as_vector_bool; IGRAPH_CHECK(igraph_vector_bool_reserve(oldbool, idx_size)); IGRAPH_CHECK(igraph_i_attribute_permutation_work_area_alloc_for_boolean(&work_area)); break; case IGRAPH_ATTRIBUTE_STRING: - str = (igraph_strvector_t*) oldrec->value; + str = oldrec->value.as_strvector; IGRAPH_CHECK(igraph_strvector_reserve(str, idx_size)); IGRAPH_CHECK(igraph_i_attribute_permutation_work_area_alloc_for_strings(&work_area)); break; default: - IGRAPH_WARNING("Unknown vertex attribute ignored"); + IGRAPH_WARNINGF( + "Vertex attribute '%s' with unknown type %d ignored", + oldrec->name, (int) oldrec->type + ); } } @@ -686,18 +606,16 @@ static igraph_error_t igraph_i_cattribute_permute_vertices_in_place( * instances for the permuted attributes and store them in an * igraph_vector_ptr_t until we are done with all of them. If any of the * allocations fail, we can destroy the igraph_vector_ptr_t safely */ - for (i = 0; i < valno; i++) { - oldrec = VECTOR(*val)[i]; - if (oldrec->type != IGRAPH_ATTRIBUTE_STRING) { - continue; + for (i = 0; i < no_attrs; i++) { + oldrec = igraph_attribute_record_list_get_ptr(attrs, i); + if (oldrec->type == IGRAPH_ATTRIBUTE_STRING) { + str = oldrec->value.as_strvector; + IGRAPH_CHECK( + igraph_i_attribute_permutation_work_area_permute_and_store_strvector( + &work_area, str, idx + ) + ); } - - str = (igraph_strvector_t*) oldrec->value; - IGRAPH_CHECK( - igraph_i_attribute_permutation_work_area_permute_and_store_strvector( - &work_area, str, idx - ) - ); } /* strings are done, and now all vectors involved in the process are @@ -705,13 +623,13 @@ static igraph_error_t igraph_i_cattribute_permute_vertices_in_place( * supposed to fail. We can safely replace the original string attribute * vectors with the permuted ones, and then proceed to the remaining * attributes */ - for (i = 0, j = 0; i < valno; i++) { - oldrec = VECTOR(*val)[i]; + for (i = 0, j = 0; i < no_attrs; i++) { + oldrec = igraph_attribute_record_list_get_ptr(attrs, i); if (oldrec->type != IGRAPH_ATTRIBUTE_STRING) { continue; } - str = (igraph_strvector_t*) oldrec->value; + str = oldrec->value.as_strvector; str_work = *((igraph_strvector_t*) VECTOR(*(work_area.strings))[j]); *((igraph_strvector_t*) VECTOR(*(work_area.strings))[j]) = *str; *str = str_work; @@ -719,24 +637,22 @@ static igraph_error_t igraph_i_cattribute_permute_vertices_in_place( } igraph_i_attribute_permutation_work_area_release_stored_strvectors(&work_area); - for (i = 0; i < valno; i++) { - oldrec = VECTOR(*val)[i]; + for (i = 0; i < no_attrs; i++) { + oldrec = igraph_attribute_record_list_get_ptr(attrs, i); switch (oldrec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: - num = (igraph_vector_t*) oldrec->value; + num = oldrec->value.as_vector; num_work = work_area.numeric; IGRAPH_ASSERT(num_work != NULL); IGRAPH_CHECK(igraph_vector_index(num, num_work, idx)); - work_area.numeric = num; - oldrec->value = num_work; + igraph_vector_swap(num, num_work); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - oldbool = (igraph_vector_bool_t*) oldrec->value; + oldbool = oldrec->value.as_vector_bool; bool_work = work_area.boolean; IGRAPH_ASSERT(bool_work != NULL); IGRAPH_CHECK(igraph_vector_bool_index(oldbool, bool_work, idx)); - work_area.boolean = oldbool; - oldrec->value = bool_work; + igraph_vector_bool_swap(oldbool, bool_work); break; case IGRAPH_ATTRIBUTE_STRING: /* nothing to do */ @@ -757,88 +673,12 @@ static igraph_error_t igraph_i_cattribute_permute_vertices( const igraph_t *graph, igraph_t *newgraph, const igraph_vector_int_t *idx ) { igraph_i_cattributes_t *attr = graph->attr, *new_attr = newgraph->attr; - igraph_vector_ptr_t *val = &attr->val, *new_val = &new_attr->val; - igraph_integer_t i, valno; - - IGRAPH_ASSERT(graph == newgraph || igraph_vector_ptr_empty(new_val)); - - /* Handle in-place permutation separately */ + igraph_attribute_record_list_t *val = &attr->val, *new_val = &new_attr->val; if (graph == newgraph) { - return igraph_i_cattribute_permute_vertices_in_place(newgraph, idx); - } - - /* New vertex attributes */ - valno = igraph_vector_ptr_size(val); - IGRAPH_CHECK(igraph_vector_ptr_resize(new_val, valno)); - IGRAPH_FINALLY(igraph_i_cattribute_clear_attribute_container, new_val); - - for (i = 0; i < valno; i++) { - igraph_attribute_record_t *oldrec = VECTOR(*val)[i]; - igraph_attribute_type_t type = oldrec->type; - igraph_vector_t *num, *newnum; - igraph_strvector_t *str, *newstr; - igraph_vector_bool_t *oldbool, *newbool; - - /* The record itself */ - igraph_attribute_record_t *new_rec = - IGRAPH_CALLOC(1, igraph_attribute_record_t); - if (! new_rec) { - IGRAPH_ERROR("Cannot create vertex attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, new_rec); - new_rec->name = strdup(oldrec->name); - if (! new_rec->name) { - IGRAPH_ERROR("Cannot create vertex attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char *) new_rec->name); - new_rec->type = oldrec->type; - - /* The data */ - switch (type) { - case IGRAPH_ATTRIBUTE_NUMERIC: - num = (igraph_vector_t*)oldrec->value; - newnum = IGRAPH_CALLOC(1, igraph_vector_t); - if (!newnum) { - IGRAPH_ERROR("Cannot permute vertex attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newnum); - IGRAPH_VECTOR_INIT_FINALLY(newnum, 0); - IGRAPH_CHECK(igraph_vector_index(num, newnum, idx)); - new_rec->value = newnum; - break; - case IGRAPH_ATTRIBUTE_BOOLEAN: - oldbool = (igraph_vector_bool_t*)oldrec->value; - newbool = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (!newbool) { - IGRAPH_ERROR("Cannot permute vertex attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newbool); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newbool, 0); - IGRAPH_CHECK(igraph_vector_bool_index(oldbool, newbool, idx)); - new_rec->value = newbool; - break; - case IGRAPH_ATTRIBUTE_STRING: - str = (igraph_strvector_t*)oldrec->value; - newstr = IGRAPH_CALLOC(1, igraph_strvector_t); - if (!newstr) { - IGRAPH_ERROR("Cannot permute vertex attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newstr); - IGRAPH_STRVECTOR_INIT_FINALLY(newstr, 0); - IGRAPH_CHECK(igraph_strvector_index(str, newstr, idx)); - new_rec->value = newstr; - break; - default: - IGRAPH_WARNING("Unknown vertex attribute ignored"); - } - - VECTOR(*new_val)[i] = new_rec; - IGRAPH_FINALLY_CLEAN(4); + return igraph_i_cattribute_permute_attribute_record_list_in_place(val, idx); + } else { + return igraph_i_cattribute_permute_attribute_record_list(val, new_val, idx); } - - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; } typedef igraph_error_t igraph_cattributes_combine_num_t(const igraph_vector_t *input, @@ -853,17 +693,11 @@ typedef igraph_error_t igraph_cattributes_combine_bool_t(const igraph_vector_boo static igraph_error_t igraph_i_cattributes_cn_sum(const igraph_attribute_record_t *oldrec, igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_t *oldv = oldrec->value; - igraph_vector_t *newv = IGRAPH_CALLOC(1, igraph_vector_t); + const igraph_vector_t *oldv = oldrec->value.as_vector; + igraph_vector_t *newv = newrec->value.as_vector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_real_t s = 0.0; igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; @@ -875,26 +709,17 @@ static igraph_error_t igraph_i_cattributes_cn_sum(const igraph_attribute_record_ VECTOR(*newv)[i] = s; } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } static igraph_error_t igraph_i_cattributes_cn_prod(const igraph_attribute_record_t *oldrec, igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_t *oldv = oldrec->value; - igraph_vector_t *newv = IGRAPH_CALLOC(1, igraph_vector_t); + const igraph_vector_t *oldv = oldrec->value.as_vector; + igraph_vector_t *newv = newrec->value.as_vector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_real_t s = 1.0; igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; @@ -906,26 +731,17 @@ static igraph_error_t igraph_i_cattributes_cn_prod(const igraph_attribute_record VECTOR(*newv)[i] = s; } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } static igraph_error_t igraph_i_cattributes_cn_min(const igraph_attribute_record_t *oldrec, igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_t *oldv = oldrec->value; - igraph_vector_t *newv = IGRAPH_CALLOC(1, igraph_vector_t); + const igraph_vector_t *oldv = oldrec->value.as_vector; + igraph_vector_t *newv = newrec->value.as_vector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; igraph_integer_t j, n = igraph_vector_int_size(idx); @@ -940,26 +756,17 @@ static igraph_error_t igraph_i_cattributes_cn_min(const igraph_attribute_record_ VECTOR(*newv)[i] = m; } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } static igraph_error_t igraph_i_cattributes_cn_max(const igraph_attribute_record_t *oldrec, igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_t *oldv = oldrec->value; - igraph_vector_t *newv = IGRAPH_CALLOC(1, igraph_vector_t); + const igraph_vector_t *oldv = oldrec->value.as_vector; + igraph_vector_t *newv = newrec->value.as_vector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; igraph_integer_t j, n = igraph_vector_int_size(idx); @@ -974,9 +781,6 @@ static igraph_error_t igraph_i_cattributes_cn_max(const igraph_attribute_record_ VECTOR(*newv)[i] = m; } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } @@ -984,17 +788,11 @@ static igraph_error_t igraph_i_cattributes_cn_random(const igraph_attribute_reco igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_t *oldv = oldrec->value; - igraph_vector_t *newv = IGRAPH_CALLOC(1, igraph_vector_t); + const igraph_vector_t *oldv = oldrec->value.as_vector; + igraph_vector_t *newv = newrec->value.as_vector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_INIT_FINALLY(newv, newlen); - RNG_BEGIN(); for (i = 0; i < newlen; i++) { @@ -1012,9 +810,6 @@ static igraph_error_t igraph_i_cattributes_cn_random(const igraph_attribute_reco RNG_END(); - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } @@ -1022,17 +817,11 @@ static igraph_error_t igraph_i_cattributes_cn_first(const igraph_attribute_recor igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_t *oldv = oldrec->value; - igraph_vector_t *newv = IGRAPH_CALLOC(1, igraph_vector_t); + const igraph_vector_t *oldv = oldrec->value.as_vector; + igraph_vector_t *newv = newrec->value.as_vector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; igraph_integer_t n = igraph_vector_int_size(idx); @@ -1043,9 +832,6 @@ static igraph_error_t igraph_i_cattributes_cn_first(const igraph_attribute_recor } } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } @@ -1053,17 +839,11 @@ static igraph_error_t igraph_i_cattributes_cn_last(const igraph_attribute_record igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_t *oldv = oldrec->value; - igraph_vector_t *newv = IGRAPH_CALLOC(1, igraph_vector_t); + const igraph_vector_t *oldv = oldrec->value.as_vector; + igraph_vector_t *newv = newrec->value.as_vector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; igraph_integer_t n = igraph_vector_int_size(idx); @@ -1074,26 +854,17 @@ static igraph_error_t igraph_i_cattributes_cn_last(const igraph_attribute_record } } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } static igraph_error_t igraph_i_cattributes_cn_mean(const igraph_attribute_record_t *oldrec, igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_t *oldv = oldrec->value; - igraph_vector_t *newv = IGRAPH_CALLOC(1, igraph_vector_t); + const igraph_vector_t *oldv = oldrec->value.as_vector; + igraph_vector_t *newv = newrec->value.as_vector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; igraph_integer_t j, n = igraph_vector_int_size(idx); @@ -1108,9 +879,6 @@ static igraph_error_t igraph_i_cattributes_cn_mean(const igraph_attribute_record VECTOR(*newv)[i] = s; } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } @@ -1119,14 +887,10 @@ static igraph_error_t igraph_i_cattributes_cn_func(const igraph_attribute_record const igraph_vector_int_list_t *merges, igraph_cattributes_combine_num_t *func) { - const igraph_vector_t *oldv = oldrec->value; + const igraph_vector_t *oldv = oldrec->value.as_vector; + igraph_vector_t *newv = newrec->value.as_vector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); - igraph_vector_t *newv = IGRAPH_CALLOC(1, igraph_vector_t); - IGRAPH_CHECK_OOM(newv, "Cannot combine attributes."); - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_INIT_FINALLY(newv, newlen); - igraph_vector_t values; IGRAPH_VECTOR_INIT_FINALLY(&values, 0); @@ -1146,8 +910,7 @@ static igraph_error_t igraph_i_cattributes_cn_func(const igraph_attribute_record } igraph_vector_destroy(&values); - IGRAPH_FINALLY_CLEAN(3); - newrec->value = newv; + IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; } @@ -1156,17 +919,11 @@ static igraph_error_t igraph_i_cattributes_cb_random(const igraph_attribute_reco igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_bool_t *oldv = oldrec->value; - igraph_vector_bool_t *newv = IGRAPH_CALLOC(1, igraph_vector_bool_t); + const igraph_vector_bool_t *oldv = oldrec->value.as_vector_bool; + igraph_vector_bool_t *newv = newrec->value.as_vector_bool; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newv, newlen); - RNG_BEGIN(); for (i = 0; i < newlen; i++) { @@ -1184,9 +941,6 @@ static igraph_error_t igraph_i_cattributes_cb_random(const igraph_attribute_reco RNG_END(); - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } @@ -1194,17 +948,11 @@ static igraph_error_t igraph_i_cattributes_cb_first(const igraph_attribute_recor igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_bool_t *oldv = oldrec->value; - igraph_vector_bool_t *newv = IGRAPH_CALLOC(1, igraph_vector_bool_t); + const igraph_vector_bool_t *oldv = oldrec->value.as_vector_bool; + igraph_vector_bool_t *newv = newrec->value.as_vector_bool; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; igraph_integer_t n = igraph_vector_int_size(idx); @@ -1215,9 +963,6 @@ static igraph_error_t igraph_i_cattributes_cb_first(const igraph_attribute_recor } } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } @@ -1225,17 +970,11 @@ static igraph_error_t igraph_i_cattributes_cb_last(const igraph_attribute_record igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_bool_t *oldv = oldrec->value; - igraph_vector_bool_t *newv = IGRAPH_CALLOC(1, igraph_vector_bool_t); + const igraph_vector_bool_t *oldv = oldrec->value.as_vector_bool; + igraph_vector_bool_t *newv = newrec->value.as_vector_bool; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; igraph_integer_t n = igraph_vector_int_size(idx); @@ -1246,9 +985,6 @@ static igraph_error_t igraph_i_cattributes_cb_last(const igraph_attribute_record } } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } @@ -1256,17 +992,11 @@ static igraph_error_t igraph_i_cattributes_cb_all_is_true(const igraph_attribute igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_bool_t *oldv = oldrec->value; - igraph_vector_bool_t *newv = IGRAPH_CALLOC(1, igraph_vector_bool_t); + const igraph_vector_bool_t *oldv = oldrec->value.as_vector_bool; + igraph_vector_bool_t *newv = newrec->value.as_vector_bool; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i, j, n, x; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; n = igraph_vector_int_size(idx); @@ -1280,9 +1010,6 @@ static igraph_error_t igraph_i_cattributes_cb_all_is_true(const igraph_attribute } } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } @@ -1290,17 +1017,11 @@ static igraph_error_t igraph_i_cattributes_cb_any_is_true(const igraph_attribute igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_bool_t *oldv = oldrec->value; - igraph_vector_bool_t *newv = IGRAPH_CALLOC(1, igraph_vector_bool_t); + const igraph_vector_bool_t *oldv = oldrec->value.as_vector_bool; + igraph_vector_bool_t *newv = newrec->value.as_vector_bool; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i, j, n, x; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newv, newlen); - for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; n = igraph_vector_int_size(idx); @@ -1314,9 +1035,6 @@ static igraph_error_t igraph_i_cattributes_cb_any_is_true(const igraph_attribute } } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } @@ -1324,17 +1042,11 @@ static igraph_error_t igraph_i_cattributes_cb_majority(const igraph_attribute_re igraph_attribute_record_t * newrec, const igraph_vector_int_list_t *merges) { - const igraph_vector_bool_t *oldv = oldrec->value; - igraph_vector_bool_t *newv = IGRAPH_CALLOC(1, igraph_vector_bool_t); + const igraph_vector_bool_t *oldv = oldrec->value.as_vector_bool; + igraph_vector_bool_t *newv = newrec->value.as_vector_bool; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i, j, n, x, num_trues; - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newv, newlen); - RNG_BEGIN(); for (i = 0; i < newlen; i++) { @@ -1363,9 +1075,6 @@ static igraph_error_t igraph_i_cattributes_cb_majority(const igraph_attribute_re RNG_END(); - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } @@ -1374,14 +1083,10 @@ static igraph_error_t igraph_i_cattributes_cb_func(const igraph_attribute_record const igraph_vector_int_list_t *merges, igraph_cattributes_combine_bool_t *func) { - const igraph_vector_bool_t *oldv = oldrec->value; + const igraph_vector_bool_t *oldv = oldrec->value.as_vector_bool; + igraph_vector_bool_t *newv = newrec->value.as_vector_bool; igraph_integer_t newlen = igraph_vector_int_list_size(merges); - igraph_vector_bool_t *newv = IGRAPH_CALLOC(1, igraph_vector_bool_t); - IGRAPH_CHECK_OOM(newv, "Cannot combine attributes."); - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newv, newlen); - igraph_vector_bool_t values; IGRAPH_VECTOR_BOOL_INIT_FINALLY(&values, 0); @@ -1401,8 +1106,7 @@ static igraph_error_t igraph_i_cattributes_cb_func(const igraph_attribute_record } igraph_vector_bool_destroy(&values); - IGRAPH_FINALLY_CLEAN(3); - newrec->value = newv; + IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; } @@ -1411,16 +1115,10 @@ static igraph_error_t igraph_i_cattributes_sn_random(const igraph_attribute_reco igraph_attribute_record_t *newrec, const igraph_vector_int_list_t *merges) { - const igraph_strvector_t *oldv = oldrec->value; + const igraph_strvector_t *oldv = oldrec->value.as_strvector; + igraph_strvector_t *newv = newrec->value.as_strvector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); igraph_integer_t i; - igraph_strvector_t *newv = IGRAPH_CALLOC(1, igraph_strvector_t); - - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_STRVECTOR_INIT_FINALLY(newv, newlen); RNG_BEGIN(); @@ -1442,25 +1140,16 @@ static igraph_error_t igraph_i_cattributes_sn_random(const igraph_attribute_reco RNG_END(); - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattributes_sn_first(const igraph_attribute_record_t *oldrec, +static igraph_error_t igraph_i_cattributes_cs_first(const igraph_attribute_record_t *oldrec, igraph_attribute_record_t *newrec, const igraph_vector_int_list_t *merges) { - const igraph_strvector_t *oldv = oldrec->value; + const igraph_strvector_t *oldv = oldrec->value.as_strvector; igraph_integer_t i, newlen = igraph_vector_int_list_size(merges); - igraph_strvector_t *newv = IGRAPH_CALLOC(1, igraph_strvector_t); - - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_STRVECTOR_INIT_FINALLY(newv, newlen); + igraph_strvector_t *newv = newrec->value.as_strvector; for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; @@ -1473,25 +1162,16 @@ static igraph_error_t igraph_i_cattributes_sn_first(const igraph_attribute_recor } } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattributes_sn_last(const igraph_attribute_record_t *oldrec, +static igraph_error_t igraph_i_cattributes_cs_last(const igraph_attribute_record_t *oldrec, igraph_attribute_record_t *newrec, const igraph_vector_int_list_t *merges) { - const igraph_strvector_t *oldv = oldrec->value; + const igraph_strvector_t *oldv = oldrec->value.as_strvector; igraph_integer_t i, newlen = igraph_vector_int_list_size(merges); - igraph_strvector_t *newv = IGRAPH_CALLOC(1, igraph_strvector_t); - - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_STRVECTOR_INIT_FINALLY(newv, newlen); + igraph_strvector_t *newv = newrec->value.as_strvector; for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; @@ -1504,25 +1184,16 @@ static igraph_error_t igraph_i_cattributes_sn_last(const igraph_attribute_record } } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattributes_sn_concat(const igraph_attribute_record_t *oldrec, +static igraph_error_t igraph_i_cattributes_cs_concat(const igraph_attribute_record_t *oldrec, igraph_attribute_record_t *newrec, const igraph_vector_int_list_t *merges) { - const igraph_strvector_t *oldv = oldrec->value; + const igraph_strvector_t *oldv = oldrec->value.as_strvector; igraph_integer_t i, newlen = igraph_vector_int_list_size(merges); - igraph_strvector_t *newv = IGRAPH_CALLOC(1, igraph_strvector_t); - - if (!newv) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_STRVECTOR_INIT_FINALLY(newv, newlen); + igraph_strvector_t *newv = newrec->value.as_strvector; for (i = 0; i < newlen; i++) { igraph_vector_int_t *idx = igraph_vector_int_list_get_ptr(merges, i);; @@ -1535,9 +1206,7 @@ static igraph_error_t igraph_i_cattributes_sn_concat(const igraph_attribute_reco len += strlen(tmp); } tmp2 = IGRAPH_CALLOC(len + 1, char); - if (!tmp2) { - IGRAPH_ERROR("Cannot combine attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } + IGRAPH_CHECK_OOM(tmp2, "Cannot combine attributes"); IGRAPH_FINALLY(igraph_free, tmp2); len = 0; for (j = 0; j < n; j++) { @@ -1551,25 +1220,18 @@ static igraph_error_t igraph_i_cattributes_sn_concat(const igraph_attribute_reco IGRAPH_FINALLY_CLEAN(1); } - IGRAPH_FINALLY_CLEAN(2); - newrec->value = newv; - return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattributes_sn_func(const igraph_attribute_record_t *oldrec, +static igraph_error_t igraph_i_cattributes_cs_func(const igraph_attribute_record_t *oldrec, igraph_attribute_record_t *newrec, const igraph_vector_int_list_t *merges, igraph_cattributes_combine_str_t *func) { - const igraph_strvector_t *oldv = oldrec->value; + const igraph_strvector_t *oldv = oldrec->value.as_strvector; + igraph_strvector_t *newv = newrec->value.as_strvector; igraph_integer_t newlen = igraph_vector_int_list_size(merges); - igraph_strvector_t *newv = IGRAPH_CALLOC(1, igraph_strvector_t); - IGRAPH_CHECK_OOM(newv, "Cannot combine attributes."); - IGRAPH_FINALLY(igraph_free, newv); - IGRAPH_STRVECTOR_INIT_FINALLY(newv, newlen); - igraph_strvector_t values; IGRAPH_STRVECTOR_INIT_FINALLY(&values, 0); @@ -1595,8 +1257,7 @@ static igraph_error_t igraph_i_cattributes_sn_func(const igraph_attribute_record } igraph_strvector_destroy(&values); - IGRAPH_FINALLY_CLEAN(3); - newrec->value = newv; + IGRAPH_FINALLY_CLEAN(1); return IGRAPH_SUCCESS; } @@ -1611,680 +1272,69 @@ static igraph_error_t igraph_i_cattributes_sn_func(const igraph_attribute_record * type of the attribute combination to \c IGRAPH_ATTRIBUTE_COMBINE_FUNCTION * and passing in a pointer to the custom combination function when specifying * attribute combinations in \ref igraph_attribute_combination() or - * \ref igraph_attribute_combination_add() . For the C attribute handler, the - * signature of the function depends on the type of the underlying attribute. - * For numeric attributes, use: - * \verbatim igraph_error_t function(const igraph_vector_t *input, igraph_real_t *output); \endverbatim - * where \p input will receive a vector containing the value of the attribute - * for all the vertices or edges being combined, and \p output must be filled - * by the function to the combined value. Similarly, for Boolean attributes, the - * function takes a boolean vector in \p input and must return the combined Boolean - * value in \p output: - * \verbatim igraph_error_t function(const igraph_vector_bool_t *input, igraph_bool_t *output); \endverbatim - * For string attributes, the signature is slightly different: - * \verbatim igraph_error_t function(const igraph_strvector_t *input, char **output); \endverbatim - * In case of strings, all strings in the input vector are \em owned by igraph - * and must not be modified or freed in the combination handler. The string - * returned to the caller in \p output remains owned by the caller; igraph will - * make a copy it and store the copy in the appropriate part of the data - * structure holding the vertex or edge attributes. - * - */ - -typedef struct { - igraph_attribute_combination_type_t type; - union { - igraph_function_pointer_t as_void; - igraph_cattributes_combine_num_t *as_num; - igraph_cattributes_combine_str_t *as_str; - igraph_cattributes_combine_bool_t *as_bool; - } func; -} igraph_attribute_combination_todo_item_t; - -static igraph_error_t igraph_i_cattribute_combine_vertices(const igraph_t *graph, - igraph_t *newgraph, - const igraph_vector_int_list_t *merges, - const igraph_attribute_combination_t *comb) { - - igraph_i_cattributes_t *attr = graph->attr; - igraph_i_cattributes_t *toattr = newgraph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_vector_ptr_t *new_val = &toattr->val; - igraph_integer_t valno = igraph_vector_ptr_size(val); - igraph_integer_t i, j, keepno = 0; - igraph_attribute_combination_todo_item_t *todo_items; - - IGRAPH_ASSERT(graph != newgraph); - IGRAPH_ASSERT(igraph_vector_ptr_empty(new_val)); - - todo_items = IGRAPH_CALLOC(valno, igraph_attribute_combination_todo_item_t); - if (!todo_items) { - IGRAPH_ERROR("Cannot combine vertex attributes", - IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, todo_items); - - for (i = 0; i < valno; i++) { - igraph_attribute_record_t *oldrec = VECTOR(*val)[i]; - const char *name = oldrec->name; - igraph_attribute_combination_type_t type; - igraph_function_pointer_t voidfunc; - IGRAPH_CHECK(igraph_attribute_combination_query(comb, name, &type, &voidfunc)); - todo_items[i].type = type; - todo_items[i].func.as_void = voidfunc; - if (type != IGRAPH_ATTRIBUTE_COMBINE_IGNORE) { - keepno++; - } - } - - IGRAPH_CHECK(igraph_vector_ptr_resize(new_val, keepno)); - IGRAPH_FINALLY(igraph_i_cattribute_clear_attribute_container, new_val); - - for (i = 0, j = 0; i < valno; i++) { - igraph_attribute_record_t *newrec, *oldrec = VECTOR(*val)[i]; - const char *name = oldrec->name; - igraph_attribute_combination_todo_item_t todo_item = todo_items[i]; - igraph_attribute_type_t attr_type = oldrec->type; - - if (todo_item.type == IGRAPH_ATTRIBUTE_COMBINE_DEFAULT || - todo_item.type == IGRAPH_ATTRIBUTE_COMBINE_IGNORE) { - continue; - } - - newrec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - if (!newrec) { - IGRAPH_ERROR("Cannot combine vertex attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newrec); - newrec->name = strdup(name); - if (!newrec->name) { - IGRAPH_ERROR("Cannot combine vertex attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char *) newrec->name); - newrec->type = attr_type; - - if (attr_type == IGRAPH_ATTRIBUTE_NUMERIC) { - switch (todo_item.type) { - case IGRAPH_ATTRIBUTE_COMBINE_FUNCTION: - IGRAPH_CHECK(igraph_i_cattributes_cn_func(oldrec, newrec, merges, - todo_item.func.as_num)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_SUM: - IGRAPH_CHECK(igraph_i_cattributes_cn_sum(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_PROD: - IGRAPH_CHECK(igraph_i_cattributes_cn_prod(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_MIN: - IGRAPH_CHECK(igraph_i_cattributes_cn_min(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_MAX: - IGRAPH_CHECK(igraph_i_cattributes_cn_max(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_RANDOM: - IGRAPH_CHECK(igraph_i_cattributes_cn_random(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_FIRST: - IGRAPH_CHECK(igraph_i_cattributes_cn_first(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_LAST: - IGRAPH_CHECK(igraph_i_cattributes_cn_last(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_MEAN: - IGRAPH_CHECK(igraph_i_cattributes_cn_mean(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_MEDIAN: - IGRAPH_ERROR("Median calculation not implemented", - IGRAPH_UNIMPLEMENTED); - break; - case IGRAPH_ATTRIBUTE_COMBINE_CONCAT: - IGRAPH_ERROR("Cannot concatenate numeric attributes", - IGRAPH_EATTRCOMBINE); - break; - default: - IGRAPH_ERROR("Unknown attribute_combination", - IGRAPH_UNIMPLEMENTED); - break; - } - } else if (attr_type == IGRAPH_ATTRIBUTE_BOOLEAN) { - switch (todo_item.type) { - case IGRAPH_ATTRIBUTE_COMBINE_FUNCTION: - IGRAPH_CHECK(igraph_i_cattributes_cb_func(oldrec, newrec, merges, - todo_item.func.as_bool)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_SUM: - case IGRAPH_ATTRIBUTE_COMBINE_MAX: - IGRAPH_CHECK(igraph_i_cattributes_cb_any_is_true(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_PROD: - case IGRAPH_ATTRIBUTE_COMBINE_MIN: - IGRAPH_CHECK(igraph_i_cattributes_cb_all_is_true(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_MEAN: - case IGRAPH_ATTRIBUTE_COMBINE_MEDIAN: - IGRAPH_CHECK(igraph_i_cattributes_cb_majority(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_RANDOM: - IGRAPH_CHECK(igraph_i_cattributes_cb_random(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_FIRST: - IGRAPH_CHECK(igraph_i_cattributes_cb_first(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_LAST: - IGRAPH_CHECK(igraph_i_cattributes_cb_last(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_CONCAT: - IGRAPH_ERROR("Cannot calculate concatenation of Booleans", - IGRAPH_EATTRCOMBINE); - break; - default: - IGRAPH_ERROR("Unknown attribute_combination", - IGRAPH_UNIMPLEMENTED); - break; - } - } else if (attr_type == IGRAPH_ATTRIBUTE_STRING) { - switch (todo_item.type) { - case IGRAPH_ATTRIBUTE_COMBINE_FUNCTION: - IGRAPH_CHECK(igraph_i_cattributes_sn_func(oldrec, newrec, merges, - todo_item.func.as_str)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_SUM: - IGRAPH_ERROR("Cannot sum strings", IGRAPH_EATTRCOMBINE); - break; - case IGRAPH_ATTRIBUTE_COMBINE_PROD: - IGRAPH_ERROR("Cannot multiply strings", IGRAPH_EATTRCOMBINE); - break; - case IGRAPH_ATTRIBUTE_COMBINE_MIN: - IGRAPH_ERROR("Cannot find minimum of strings", - IGRAPH_EATTRCOMBINE); - break; - case IGRAPH_ATTRIBUTE_COMBINE_MAX: - IGRAPH_ERROR("Cannot find maximum of strings", - IGRAPH_EATTRCOMBINE); - break; - case IGRAPH_ATTRIBUTE_COMBINE_MEAN: - IGRAPH_ERROR("Cannot calculate mean of strings", - IGRAPH_EATTRCOMBINE); - break; - case IGRAPH_ATTRIBUTE_COMBINE_MEDIAN: - IGRAPH_ERROR("Cannot calculate median of strings", - IGRAPH_EATTRCOMBINE); - break; - case IGRAPH_ATTRIBUTE_COMBINE_RANDOM: - IGRAPH_CHECK(igraph_i_cattributes_sn_random(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_FIRST: - IGRAPH_CHECK(igraph_i_cattributes_sn_first(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_LAST: - IGRAPH_CHECK(igraph_i_cattributes_sn_last(oldrec, newrec, merges)); - break; - case IGRAPH_ATTRIBUTE_COMBINE_CONCAT: - IGRAPH_CHECK(igraph_i_cattributes_sn_concat(oldrec, newrec, merges)); - break; - default: - IGRAPH_ERROR("Unknown attribute_combination", - IGRAPH_UNIMPLEMENTED); - break; - } - } else { - IGRAPH_ERROR("Unknown attribute type, this should not happen", - IGRAPH_UNIMPLEMENTED); - } - - VECTOR(*new_val)[j] = newrec; - IGRAPH_FINALLY_CLEAN(2); /* newrec->name and newrec */ - - j++; - } - - IGRAPH_FREE(todo_items); - IGRAPH_FINALLY_CLEAN(2); - - return IGRAPH_SUCCESS; -} - -static igraph_error_t igraph_i_cattribute_add_edges_inner(igraph_t *graph, const igraph_vector_int_t *edges, - igraph_vector_ptr_t *nattr) { - - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t ealno = igraph_vector_ptr_size(eal); - igraph_integer_t ne = igraph_vector_int_size(edges) / 2; - igraph_integer_t origlen = igraph_ecount(graph) - ne; - igraph_integer_t nattrno = nattr == 0 ? 0 : igraph_vector_ptr_size(nattr); - igraph_vector_int_t news; - igraph_integer_t newattrs, i; - - /* First add the new attributes if any */ - newattrs = 0; - IGRAPH_VECTOR_INT_INIT_FINALLY(&news, 0); - for (i = 0; i < nattrno; i++) { - igraph_attribute_record_t *nattr_entry = VECTOR(*nattr)[i]; - const char *nname = nattr_entry->name; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(eal, nname, &j); - if (!l) { - newattrs++; - IGRAPH_CHECK(igraph_vector_int_push_back(&news, i)); - } else { - /* check types */ - if (nattr_entry->type != - ((igraph_attribute_record_t*)VECTOR(*eal)[j])->type) { - IGRAPH_ERROR("You cannot mix attribute types", IGRAPH_EINVAL); - } - } - } - - /* Add NaN/false/"" for the existing vertices for numeric, boolean and string attributes. */ - if (newattrs != 0) { - for (i = 0; i < newattrs; i++) { - igraph_attribute_record_t *tmp = VECTOR(*nattr)[ VECTOR(news)[i] ]; - igraph_attribute_record_t *newrec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_attribute_type_t type = tmp->type; - if (!newrec) { - IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newrec); - newrec->type = type; - newrec->name = strdup(tmp->name); - if (!newrec->name) { - IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)newrec->name); - if (type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *newnum = IGRAPH_CALLOC(1, igraph_vector_t); - if (!newnum) { - IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newnum); - IGRAPH_VECTOR_INIT_FINALLY(newnum, origlen); - newrec->value = newnum; - igraph_vector_fill(newnum, IGRAPH_NAN); - } else if (type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *newbool = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (!newbool) { - IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newbool); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newbool, origlen); - newrec->value = newbool; - igraph_vector_bool_fill(newbool, false); - } else if (type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *newstr = IGRAPH_CALLOC(1, igraph_strvector_t); - if (!newstr) { - IGRAPH_ERROR("Cannot add attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newstr); - IGRAPH_STRVECTOR_INIT_FINALLY(newstr, origlen); - newrec->value = newstr; - } - IGRAPH_CHECK(igraph_vector_ptr_push_back(eal, newrec)); - IGRAPH_FINALLY_CLEAN(4); - } - ealno = igraph_vector_ptr_size(eal); - } - - /* Now append the new values */ - for (i = 0; i < ealno; i++) { - igraph_attribute_record_t *oldrec = VECTOR(*eal)[i]; - igraph_attribute_record_t *newrec = NULL; - const char *name = oldrec->name; - igraph_integer_t j = -1; - igraph_bool_t l = false; - if (nattr) { - l = igraph_i_cattribute_find(nattr, name, &j); - } - if (l) { - /* This attribute is present in nattr */ - igraph_vector_t *oldnum, *newnum; - igraph_strvector_t *oldstr, *newstr; - igraph_vector_bool_t *oldbool, *newbool; - newrec = VECTOR(*nattr)[j]; - oldnum = (igraph_vector_t*)oldrec->value; - newnum = (igraph_vector_t*)newrec->value; - oldstr = (igraph_strvector_t*)oldrec->value; - newstr = (igraph_strvector_t*)newrec->value; - oldbool = (igraph_vector_bool_t*)oldrec->value; - newbool = (igraph_vector_bool_t*)newrec->value; - if (oldrec->type != newrec->type) { - IGRAPH_ERROR("Attribute types do not match.", IGRAPH_EINVAL); - } - switch (oldrec->type) { - case IGRAPH_ATTRIBUTE_NUMERIC: - if (ne != igraph_vector_size(newnum)) { - IGRAPH_ERROR("Invalid numeric attribute length.", IGRAPH_EINVAL); - } - IGRAPH_CHECK(igraph_vector_append(oldnum, newnum)); - break; - case IGRAPH_ATTRIBUTE_STRING: - if (ne != igraph_strvector_size(newstr)) { - IGRAPH_ERROR("Invalid string attribute length.", IGRAPH_EINVAL); - } - IGRAPH_CHECK(igraph_strvector_append(oldstr, newstr)); - break; - case IGRAPH_ATTRIBUTE_BOOLEAN: - if (ne != igraph_vector_bool_size(newbool)) { - IGRAPH_ERROR("Invalid boolean attribute length.", IGRAPH_EINVAL); - } - IGRAPH_CHECK(igraph_vector_bool_append(oldbool, newbool)); - break; - default: - IGRAPH_WARNING("Invalid attribute type."); - break; - } - } else { - /* No such attribute, append NaN/false/"". */ - igraph_vector_t *oldnum = (igraph_vector_t *)oldrec->value; - igraph_strvector_t *oldstr = (igraph_strvector_t*)oldrec->value; - igraph_vector_bool_t *oldbool = (igraph_vector_bool_t *)oldrec->value; - switch (oldrec->type) { - case IGRAPH_ATTRIBUTE_NUMERIC: - IGRAPH_CHECK(igraph_vector_resize(oldnum, origlen + ne)); - for (j = origlen; j < origlen + ne; j++) { - VECTOR(*oldnum)[j] = IGRAPH_NAN; - } - break; - case IGRAPH_ATTRIBUTE_STRING: - IGRAPH_CHECK(igraph_strvector_resize(oldstr, origlen + ne)); - break; - case IGRAPH_ATTRIBUTE_BOOLEAN: - IGRAPH_CHECK(igraph_vector_bool_resize(oldbool, origlen + ne)); - for (j = origlen; j < origlen + ne; j++) { - VECTOR(*oldbool)[j] = 0; - } - break; - default: - IGRAPH_WARNING("Invalid attribute type"); - break; - } - } - } - - igraph_vector_int_destroy(&news); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} - -static igraph_error_t igraph_i_cattribute_add_edges(igraph_t *graph, const igraph_vector_int_t *edges, - igraph_vector_ptr_t *nattr) { - /* Record information needed to restore attribute vector sizes */ - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t ne = igraph_vector_int_size(edges) / 2; - igraph_integer_t origlen = igraph_ecount(graph) - ne; - - /* Attempt adding attributes */ - igraph_error_t err = igraph_i_cattribute_add_edges_inner(graph, edges, nattr); - if (err != IGRAPH_SUCCESS) { - /* If unsuccessful, revert attribute vector sizes. - * The following function assumes that all attributes vectors that - * are present have a length at least as great as origlen. - * This is true at the moment because any new attributes that are - * added to the graph are created directly at 'origlen' instead of - * being created at smaller sizes and resized later. - * - * NOTE: While this ensures that all attribute vector lengths are - * correct, it does not ensure that no extra attributes have - * been added to the graph. However, the presence of extra - * attributes does not make the attribute table inconsistent - * like the incorrect attribute vector lengths would. - */ - igraph_i_cattribute_revert_attribute_vector_sizes(eal, origlen); - } - return err; -} - -static igraph_error_t igraph_i_cattribute_permute_edges_in_place( - igraph_t *graph, const igraph_vector_int_t *idx -) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t ealno = igraph_vector_ptr_size(eal); - igraph_integer_t i, j; - igraph_attribute_record_t *oldrec; - igraph_vector_t *num, *num_work; - igraph_strvector_t *str, str_work; - igraph_vector_bool_t *oldbool, *bool_work; - igraph_i_attribute_permutation_work_area_t work_area; - igraph_integer_t idx_size = igraph_vector_int_size(idx); - - /* shortcut: don't allocate anything if there are no attributes */ - if (ealno == 0) { - return IGRAPH_SUCCESS; - } - - IGRAPH_CHECK(igraph_i_attribute_permutation_work_area_init(&work_area, idx_size)); - IGRAPH_FINALLY(igraph_i_attribute_permutation_work_area_destroy, &work_area); - for (i = 0; i < ealno; i++) { - oldrec = VECTOR(*eal)[i]; - switch (oldrec->type) { - case IGRAPH_ATTRIBUTE_NUMERIC: - num = (igraph_vector_t*) oldrec->value; - IGRAPH_CHECK(igraph_vector_reserve(num, idx_size)); - IGRAPH_CHECK(igraph_i_attribute_permutation_work_area_alloc_for_numeric(&work_area)); - break; - - case IGRAPH_ATTRIBUTE_BOOLEAN: - oldbool = (igraph_vector_bool_t*) oldrec->value; - IGRAPH_CHECK(igraph_vector_bool_reserve(oldbool, idx_size)); - IGRAPH_CHECK(igraph_i_attribute_permutation_work_area_alloc_for_boolean(&work_area)); - break; - - case IGRAPH_ATTRIBUTE_STRING: - str = (igraph_strvector_t*) oldrec->value; - IGRAPH_CHECK(igraph_strvector_reserve(str, idx_size)); - IGRAPH_CHECK(igraph_i_attribute_permutation_work_area_alloc_for_strings(&work_area)); - break; - - default: - IGRAPH_WARNING("Unknown edge attribute ignored"); - } - } - - /* let's do string attributes first because these might need extra - * allocations that can fail. The strategy is to build new igraph_strvector_t - * instances for the permuted attributes and store them in an - * igraph_vector_ptr_t until we are done with all of them. If any of the - * allocations fail, we can destroy the igraph_vector_ptr_t safely */ - for (i = 0; i < ealno; i++) { - oldrec = VECTOR(*eal)[i]; - if (oldrec->type != IGRAPH_ATTRIBUTE_STRING) { - continue; - } - - str = (igraph_strvector_t*) oldrec->value; - IGRAPH_CHECK( - igraph_i_attribute_permutation_work_area_permute_and_store_strvector( - &work_area, str, idx - ) - ); - } - - /* strings are done, and now all vectors involved in the process are - * as large as they should be (or larger) so the operations below are not - * supposed to fail. We can safely replace the original string attribute - * vectors with the permuted ones, and then proceed to the remaining - * attributes */ - for (i = 0, j = 0; i < ealno; i++) { - oldrec = VECTOR(*eal)[i]; - if (oldrec->type != IGRAPH_ATTRIBUTE_STRING) { - continue; - } - - str = (igraph_strvector_t*) oldrec->value; - str_work = *((igraph_strvector_t*) VECTOR(*(work_area.strings))[j]); - *((igraph_strvector_t*) VECTOR(*(work_area.strings))[j]) = *str; - *str = str_work; - j++; - } - igraph_i_attribute_permutation_work_area_release_stored_strvectors(&work_area); - - /* now all vectors involved in the process are as large as they should be - * (or larger) so the operations below are not supposed to fail -- except - * for string operations that still do some extra allocations and we are - * not prepared for the failures of those. This must still be fixed. */ - for (i = 0; i < ealno; i++) { - oldrec = VECTOR(*eal)[i]; - switch (oldrec->type) { - case IGRAPH_ATTRIBUTE_NUMERIC: - num = (igraph_vector_t*) oldrec->value; - num_work = work_area.numeric; - IGRAPH_ASSERT(num_work != NULL); - IGRAPH_CHECK(igraph_vector_index(num, num_work, idx)); - work_area.numeric = num; - oldrec->value = num_work; - break; - case IGRAPH_ATTRIBUTE_BOOLEAN: - oldbool = (igraph_vector_bool_t*) oldrec->value; - bool_work = work_area.boolean; - IGRAPH_ASSERT(bool_work != NULL); - IGRAPH_CHECK(igraph_vector_bool_index(oldbool, bool_work, idx)); - work_area.boolean = oldbool; - oldrec->value = bool_work; - break; - case IGRAPH_ATTRIBUTE_STRING: - /* nothing to do */ - break; - default: - /* already warned */ - break; - } - } - - igraph_i_attribute_permutation_work_area_destroy(&work_area); - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} - -static igraph_error_t igraph_i_cattribute_permute_edges(const igraph_t *graph, - igraph_t *newgraph, - const igraph_vector_int_t *idx) { - - igraph_i_cattributes_t *attr = graph->attr, *new_attr = newgraph->attr; - igraph_vector_ptr_t *eal = &attr->eal, *new_eal = &new_attr->eal; - igraph_integer_t i, ealno; - - IGRAPH_ASSERT(graph == newgraph || igraph_vector_ptr_empty(new_eal)); - - if (graph == newgraph) { - return igraph_i_cattribute_permute_edges_in_place(newgraph, idx); - } - - /* New edge attributes */ - ealno = igraph_vector_ptr_size(eal); - IGRAPH_ASSERT(igraph_vector_ptr_empty(new_eal)); - IGRAPH_CHECK(igraph_vector_ptr_resize(new_eal, ealno)); - IGRAPH_FINALLY(igraph_i_cattribute_clear_attribute_container, new_eal); - - for (i = 0; i < ealno; i++) { - igraph_attribute_record_t *oldrec = VECTOR(*eal)[i]; - igraph_attribute_type_t type = oldrec->type; - igraph_vector_t *num, *newnum; - igraph_strvector_t *str, *newstr; - igraph_vector_bool_t *oldbool, *newbool; - - /* The record itself */ - igraph_attribute_record_t *new_rec = - IGRAPH_CALLOC(1, igraph_attribute_record_t); - if (!new_rec) { - IGRAPH_ERROR("Cannot create edge attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, new_rec); - new_rec->name = strdup(oldrec->name); - if (! new_rec->name) { - IGRAPH_ERROR("Cannot create edge attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char *) new_rec->name); - new_rec->type = oldrec->type; - - switch (type) { - case IGRAPH_ATTRIBUTE_NUMERIC: - num = (igraph_vector_t*) oldrec->value; - newnum = IGRAPH_CALLOC(1, igraph_vector_t); - if (!newnum) { - IGRAPH_ERROR("Cannot permute edge attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newnum); - IGRAPH_VECTOR_INIT_FINALLY(newnum, 0); - IGRAPH_CHECK(igraph_vector_index(num, newnum, idx)); - new_rec->value = newnum; - break; - case IGRAPH_ATTRIBUTE_STRING: - str = (igraph_strvector_t*)oldrec->value; - newstr = IGRAPH_CALLOC(1, igraph_strvector_t); - if (!newstr) { - IGRAPH_ERROR("Cannot permute edge attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newstr); - IGRAPH_STRVECTOR_INIT_FINALLY(newstr, 0); - IGRAPH_CHECK(igraph_strvector_index(str, newstr, idx)); - new_rec->value = newstr; - break; - case IGRAPH_ATTRIBUTE_BOOLEAN: - oldbool = (igraph_vector_bool_t*) oldrec->value; - newbool = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (!newbool) { - IGRAPH_ERROR("Cannot permute edge attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newbool); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(newbool, 0); - IGRAPH_CHECK(igraph_vector_bool_index(oldbool, newbool, idx)); - new_rec->value = newbool; - break; - default: - IGRAPH_WARNING("Unknown edge attribute ignored"); - } - VECTOR(*new_eal)[i] = new_rec; - IGRAPH_FINALLY_CLEAN(4); - } - IGRAPH_FINALLY_CLEAN(1); - - return IGRAPH_SUCCESS; -} + * \ref igraph_attribute_combination_add() . For the C attribute handler, the + * signature of the function depends on the type of the underlying attribute. + * For numeric attributes, use: + * \verbatim igraph_error_t function(const igraph_vector_t *input, igraph_real_t *output); \endverbatim + * where \p input will receive a vector containing the value of the attribute + * for all the vertices or edges being combined, and \p output must be filled + * by the function to the combined value. Similarly, for Boolean attributes, the + * function takes a boolean vector in \p input and must return the combined Boolean + * value in \p output: + * \verbatim igraph_error_t function(const igraph_vector_bool_t *input, igraph_bool_t *output); \endverbatim + * For string attributes, the signature is slightly different: + * \verbatim igraph_error_t function(const igraph_strvector_t *input, char **output); \endverbatim + * In case of strings, all strings in the input vector are \em owned by igraph + * and must not be modified or freed in the combination handler. The string + * returned to the caller in \p output remains owned by the caller; igraph will + * make a copy it and store the copy in the appropriate part of the data + * structure holding the vertex or edge attributes. + * + */ -static igraph_error_t igraph_i_cattribute_combine_edges(const igraph_t *graph, - igraph_t *newgraph, - const igraph_vector_int_list_t *merges, - const igraph_attribute_combination_t *comb) { +typedef struct { + igraph_attribute_combination_type_t type; + union { + igraph_function_pointer_t as_void; + igraph_cattributes_combine_num_t *as_num; + igraph_cattributes_combine_str_t *as_str; + igraph_cattributes_combine_bool_t *as_bool; + } func; +} igraph_attribute_combination_todo_item_t; - igraph_i_cattributes_t *attr = graph->attr; - igraph_i_cattributes_t *toattr = newgraph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_vector_ptr_t *new_eal = &toattr->eal; - igraph_integer_t ealno = igraph_vector_ptr_size(eal); - igraph_integer_t i, j, keepno = 0; +static igraph_error_t igraph_i_cattribute_combine_attribute_record_lists( + igraph_attribute_record_list_t *attrs, igraph_attribute_record_list_t *new_attrs, + const igraph_vector_int_list_t *merges, const igraph_attribute_combination_t *comb +) { + igraph_integer_t no_attrs = igraph_attribute_record_list_size(attrs); + igraph_integer_t i, j, to_keep = 0; igraph_attribute_combination_todo_item_t *todo_items; - IGRAPH_ASSERT(graph != newgraph); - IGRAPH_ASSERT(igraph_vector_ptr_empty(new_eal)); + IGRAPH_ASSERT(attrs != new_attrs); + IGRAPH_ASSERT(igraph_attribute_record_list_empty(new_attrs)); - todo_items = IGRAPH_CALLOC(ealno, igraph_attribute_combination_todo_item_t); - if (!todo_items) { - IGRAPH_ERROR("Cannot combine edge attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } + todo_items = IGRAPH_CALLOC(no_attrs, igraph_attribute_combination_todo_item_t); + IGRAPH_CHECK_OOM(todo_items, "Cannot combine attributes"); IGRAPH_FINALLY(igraph_free, todo_items); - for (i = 0; i < ealno; i++) { - igraph_attribute_record_t *oldrec = VECTOR(*eal)[i]; + for (i = 0; i < no_attrs; i++) { + igraph_attribute_record_t *oldrec = igraph_attribute_record_list_get_ptr(attrs, i); const char *name = oldrec->name; - igraph_attribute_combination_type_t todo; + igraph_attribute_combination_type_t type; igraph_function_pointer_t voidfunc; - IGRAPH_CHECK(igraph_attribute_combination_query(comb, name, &todo, &voidfunc)); - todo_items[i].type = todo; + IGRAPH_CHECK(igraph_attribute_combination_query(comb, name, &type, &voidfunc)); + todo_items[i].type = type; todo_items[i].func.as_void = voidfunc; - if (todo != IGRAPH_ATTRIBUTE_COMBINE_IGNORE) { - keepno++; + if (type != IGRAPH_ATTRIBUTE_COMBINE_IGNORE) { + to_keep++; } } - IGRAPH_CHECK(igraph_vector_ptr_resize(new_eal, keepno)); - IGRAPH_FINALLY(igraph_i_cattribute_clear_attribute_container, new_eal); + IGRAPH_FINALLY(igraph_attribute_record_list_clear, new_attrs); - for (i = 0, j = 0; i < ealno; i++) { - igraph_attribute_record_t *newrec, *oldrec = VECTOR(*eal)[i]; + for (i = 0, j = 0; i < no_attrs; i++) { + igraph_attribute_record_t *oldrec = igraph_attribute_record_list_get_ptr(attrs, i); + igraph_attribute_record_t newrec; const char *name = oldrec->name; igraph_attribute_combination_todo_item_t todo_item = todo_items[i]; igraph_attribute_type_t attr_type = oldrec->type; @@ -2294,47 +1344,40 @@ static igraph_error_t igraph_i_cattribute_combine_edges(const igraph_t *graph, continue; } - newrec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - if (!newrec) { - IGRAPH_ERROR("Cannot combine edge attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, newrec); - newrec->name = strdup(name); - if (! newrec->name) { - IGRAPH_ERROR("Cannot combine edge attributes", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char *) newrec->name); - newrec->type = attr_type; + IGRAPH_CHECK(igraph_attribute_record_init(&newrec, name, attr_type)); + IGRAPH_FINALLY(igraph_attribute_record_destroy, &newrec); + + IGRAPH_CHECK(igraph_attribute_record_resize(&newrec, igraph_vector_int_list_size(merges))); if (attr_type == IGRAPH_ATTRIBUTE_NUMERIC) { switch (todo_item.type) { case IGRAPH_ATTRIBUTE_COMBINE_FUNCTION: - IGRAPH_CHECK(igraph_i_cattributes_cn_func(oldrec, newrec, merges, + IGRAPH_CHECK(igraph_i_cattributes_cn_func(oldrec, &newrec, merges, todo_item.func.as_num)); break; case IGRAPH_ATTRIBUTE_COMBINE_SUM: - IGRAPH_CHECK(igraph_i_cattributes_cn_sum(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cn_sum(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_PROD: - IGRAPH_CHECK(igraph_i_cattributes_cn_prod(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cn_prod(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_MIN: - IGRAPH_CHECK(igraph_i_cattributes_cn_min(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cn_min(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_MAX: - IGRAPH_CHECK(igraph_i_cattributes_cn_max(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cn_max(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_RANDOM: - IGRAPH_CHECK(igraph_i_cattributes_cn_random(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cn_random(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_FIRST: - IGRAPH_CHECK(igraph_i_cattributes_cn_first(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cn_first(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_LAST: - IGRAPH_CHECK(igraph_i_cattributes_cn_last(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cn_last(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_MEAN: - IGRAPH_CHECK(igraph_i_cattributes_cn_mean(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cn_mean(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_MEDIAN: IGRAPH_ERROR("Median calculation not implemented", @@ -2345,50 +1388,50 @@ static igraph_error_t igraph_i_cattribute_combine_edges(const igraph_t *graph, IGRAPH_EATTRCOMBINE); break; default: - IGRAPH_ERROR("Unknown attribute_combination", + IGRAPH_ERROR("Unknown attribute combination", IGRAPH_UNIMPLEMENTED); break; } } else if (attr_type == IGRAPH_ATTRIBUTE_BOOLEAN) { switch (todo_item.type) { case IGRAPH_ATTRIBUTE_COMBINE_FUNCTION: - IGRAPH_CHECK(igraph_i_cattributes_cb_func(oldrec, newrec, merges, + IGRAPH_CHECK(igraph_i_cattributes_cb_func(oldrec, &newrec, merges, todo_item.func.as_bool)); break; case IGRAPH_ATTRIBUTE_COMBINE_SUM: case IGRAPH_ATTRIBUTE_COMBINE_MAX: - IGRAPH_CHECK(igraph_i_cattributes_cb_any_is_true(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cb_any_is_true(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_PROD: case IGRAPH_ATTRIBUTE_COMBINE_MIN: - IGRAPH_CHECK(igraph_i_cattributes_cb_all_is_true(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cb_all_is_true(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_MEAN: case IGRAPH_ATTRIBUTE_COMBINE_MEDIAN: - IGRAPH_CHECK(igraph_i_cattributes_cb_majority(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cb_majority(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_RANDOM: - IGRAPH_CHECK(igraph_i_cattributes_cb_random(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cb_random(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_FIRST: - IGRAPH_CHECK(igraph_i_cattributes_cb_first(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cb_first(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_LAST: - IGRAPH_CHECK(igraph_i_cattributes_cb_last(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cb_last(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_CONCAT: IGRAPH_ERROR("Cannot calculate concatenation of Booleans", IGRAPH_EATTRCOMBINE); break; default: - IGRAPH_ERROR("Unknown attribute_combination", + IGRAPH_ERROR("Unknown attribute combination", IGRAPH_UNIMPLEMENTED); break; } } else if (attr_type == IGRAPH_ATTRIBUTE_STRING) { switch (todo_item.type) { case IGRAPH_ATTRIBUTE_COMBINE_FUNCTION: - IGRAPH_CHECK(igraph_i_cattributes_sn_func(oldrec, newrec, merges, + IGRAPH_CHECK(igraph_i_cattributes_cs_func(oldrec, &newrec, merges, todo_item.func.as_str)); break; case IGRAPH_ATTRIBUTE_COMBINE_SUM: @@ -2414,19 +1457,19 @@ static igraph_error_t igraph_i_cattribute_combine_edges(const igraph_t *graph, IGRAPH_EATTRCOMBINE); break; case IGRAPH_ATTRIBUTE_COMBINE_RANDOM: - IGRAPH_CHECK(igraph_i_cattributes_sn_random(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_sn_random(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_FIRST: - IGRAPH_CHECK(igraph_i_cattributes_sn_first(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cs_first(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_LAST: - IGRAPH_CHECK(igraph_i_cattributes_sn_last(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cs_last(oldrec, &newrec, merges)); break; case IGRAPH_ATTRIBUTE_COMBINE_CONCAT: - IGRAPH_CHECK(igraph_i_cattributes_sn_concat(oldrec, newrec, merges)); + IGRAPH_CHECK(igraph_i_cattributes_cs_concat(oldrec, &newrec, merges)); break; default: - IGRAPH_ERROR("Unknown attribute_combination", + IGRAPH_ERROR("Unknown attribute combination", IGRAPH_UNIMPLEMENTED); break; } @@ -2435,10 +1478,8 @@ static igraph_error_t igraph_i_cattribute_combine_edges(const igraph_t *graph, IGRAPH_UNIMPLEMENTED); } - VECTOR(*new_eal)[j] = newrec; - IGRAPH_FINALLY_CLEAN(2); /* newrec and newrc->name */ - - j++; + IGRAPH_CHECK(igraph_attribute_record_list_push_back(new_attrs, &newrec)); + IGRAPH_FINALLY_CLEAN(1); /* ownership of newrec transferred */ } IGRAPH_FREE(todo_items); @@ -2447,6 +1488,49 @@ static igraph_error_t igraph_i_cattribute_combine_edges(const igraph_t *graph, return IGRAPH_SUCCESS; } +static igraph_error_t igraph_i_cattribute_combine_vertices( + const igraph_t *graph, igraph_t *newgraph, + const igraph_vector_int_list_t *merges, const igraph_attribute_combination_t *comb +) { + igraph_i_cattributes_t *attr = graph->attr; + igraph_i_cattributes_t *toattr = newgraph->attr; + return igraph_i_cattribute_combine_attribute_record_lists( + &attr->val, &toattr->val, merges, comb + ); +} + +static igraph_error_t igraph_i_cattribute_add_edges( + igraph_t *graph, const igraph_vector_int_t *edges, + const igraph_attribute_record_list_t *nattr +) { + igraph_integer_t ne = igraph_vector_int_size(edges) / 2; + igraph_i_cattributes_t *attr = graph->attr; + return igraph_i_cattribute_add_vertices_or_edges(&attr->eal, igraph_ecount(graph), ne, nattr); +} + +static igraph_error_t igraph_i_cattribute_permute_edges(const igraph_t *graph, + igraph_t *newgraph, + const igraph_vector_int_t *idx) { + igraph_i_cattributes_t *attr = graph->attr, *new_attr = newgraph->attr; + igraph_attribute_record_list_t *eal = &attr->eal, *new_eal = &new_attr->eal; + if (graph == newgraph) { + return igraph_i_cattribute_permute_attribute_record_list_in_place(eal, idx); + } else { + return igraph_i_cattribute_permute_attribute_record_list(eal, new_eal, idx); + } +} + +static igraph_error_t igraph_i_cattribute_combine_edges( + const igraph_t *graph, igraph_t *newgraph, + const igraph_vector_int_list_t *merges, const igraph_attribute_combination_t *comb +) { + igraph_i_cattributes_t *attr = graph->attr; + igraph_i_cattributes_t *toattr = newgraph->attr; + return igraph_i_cattribute_combine_attribute_record_lists( + &attr->eal, &toattr->eal, merges, comb + ); +} + static igraph_error_t igraph_i_cattribute_get_info(const igraph_t *graph, igraph_strvector_t *gnames, igraph_vector_int_t *gtypes, @@ -2458,14 +1542,14 @@ static igraph_error_t igraph_i_cattribute_get_info(const igraph_t *graph, igraph_strvector_t *names[3] = { gnames, vnames, enames }; igraph_vector_int_t *types[3] = { gtypes, vtypes, etypes }; igraph_i_cattributes_t *at = graph->attr; - igraph_vector_ptr_t *attr[3] = { &at->gal, &at->val, &at->eal }; + igraph_attribute_record_list_t *attr[3] = { &at->gal, &at->val, &at->eal }; igraph_integer_t i, j; for (i = 0; i < 3; i++) { igraph_strvector_t *n = names[i]; igraph_vector_int_t *t = types[i]; - igraph_vector_ptr_t *al = attr[i]; - igraph_integer_t len = igraph_vector_ptr_size(al); + igraph_attribute_record_list_t *al = attr[i]; + igraph_integer_t len = igraph_attribute_record_list_size(al); if (n) { IGRAPH_CHECK(igraph_strvector_resize(n, len)); @@ -2475,7 +1559,7 @@ static igraph_error_t igraph_i_cattribute_get_info(const igraph_t *graph, } for (j = 0; j < len; j++) { - igraph_attribute_record_t *rec = VECTOR(*al)[j]; + igraph_attribute_record_t *rec = igraph_attribute_record_list_get_ptr(al, j); const char *name = rec->name; igraph_attribute_type_t type = rec->type; if (n) { @@ -2494,134 +1578,95 @@ static igraph_bool_t igraph_i_cattribute_has_attr(const igraph_t *graph, igraph_attribute_elemtype_t type, const char *name) { igraph_i_cattributes_t *at = graph->attr; - igraph_vector_ptr_t *attr[3] = { &at->gal, &at->val, &at->eal }; - igraph_integer_t attrnum; - switch (type) { case IGRAPH_ATTRIBUTE_GRAPH: - attrnum = 0; - break; + return igraph_i_cattribute_find_index(&at->gal, name) >= 0; case IGRAPH_ATTRIBUTE_VERTEX: - attrnum = 1; - break; + return igraph_i_cattribute_find_index(&at->val, name) >= 0; case IGRAPH_ATTRIBUTE_EDGE: - attrnum = 2; - break; + return igraph_i_cattribute_find_index(&at->eal, name) >= 0; default: IGRAPH_ERROR("Unknown attribute element type", IGRAPH_EINVAL); break; } - return igraph_i_cattribute_find(attr[attrnum], name, 0); + return 0; } static igraph_error_t igraph_i_cattribute_gettype(const igraph_t *graph, igraph_attribute_type_t *type, igraph_attribute_elemtype_t elemtype, const char *name) { - igraph_integer_t attrnum; igraph_attribute_record_t *rec; igraph_i_cattributes_t *at = graph->attr; - igraph_vector_ptr_t *attr[3] = { &at->gal, &at->val, &at->eal }; - igraph_vector_ptr_t *al; - igraph_integer_t j; - igraph_bool_t l = false; + igraph_attribute_record_list_t *al; switch (elemtype) { case IGRAPH_ATTRIBUTE_GRAPH: - attrnum = 0; + al = &at->gal; break; case IGRAPH_ATTRIBUTE_VERTEX: - attrnum = 1; + al = &at->val; break; case IGRAPH_ATTRIBUTE_EDGE: - attrnum = 2; + al = &at->eal; break; default: IGRAPH_ERROR("Unknown attribute element type", IGRAPH_EINVAL); break; } - al = attr[attrnum]; - l = igraph_i_cattribute_find(al, name, &j); - if (!l) { - IGRAPH_ERROR("Unknown attribute", IGRAPH_EINVAL); - } - rec = VECTOR(*al)[j]; + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(al, name, IGRAPH_ATTRIBUTE_UNSPECIFIED, &rec)); *type = rec->type; return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattribute_get_numeric_graph_attr(const igraph_t *graph, - const char *name, - igraph_vector_t *value) { +static igraph_error_t igraph_i_cattribute_get_numeric_graph_attr( + const igraph_t *graph, const char *name, igraph_vector_t *value +) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t j; + igraph_attribute_record_list_t *gal = &attr->gal; igraph_attribute_record_t *rec; igraph_vector_t *num; - igraph_bool_t l = igraph_i_cattribute_find(gal, name, &j); - if (!l) { - IGRAPH_ERRORF("The graph attribute '%s' does not exist.", IGRAPH_EINVAL, name); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(gal, name, IGRAPH_ATTRIBUTE_NUMERIC, &rec)); - rec = VECTOR(*gal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_NUMERIC) { - IGRAPH_ERRORF("Numeric graph attribute '%s' expected, got %s.", IGRAPH_EINVAL, name, attribute_type_name(rec->type)); - } - num = (igraph_vector_t*)rec->value; + num = rec->value.as_vector; IGRAPH_CHECK(igraph_vector_resize(value, 1)); VECTOR(*value)[0] = VECTOR(*num)[0]; return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattribute_get_bool_graph_attr(const igraph_t *graph, - const char *name, - igraph_vector_bool_t *value) { +static igraph_error_t igraph_i_cattribute_get_bool_graph_attr( + const igraph_t *graph, const char *name, igraph_vector_bool_t *value +) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t j; + igraph_attribute_record_list_t *gal = &attr->gal; igraph_attribute_record_t *rec; igraph_vector_bool_t *log; - igraph_bool_t l = igraph_i_cattribute_find(gal, name, &j); - if (!l) { - IGRAPH_ERRORF("The graph attribute '%s' does not exist.", IGRAPH_EINVAL, name); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(gal, name, IGRAPH_ATTRIBUTE_BOOLEAN, &rec)); - rec = VECTOR(*gal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_BOOLEAN) { - IGRAPH_ERRORF("Boolean graph attribute '%s' expected, got %s.", IGRAPH_EINVAL, name, attribute_type_name(rec->type)); - } - log = (igraph_vector_bool_t*)rec->value; + log = rec->value.as_vector_bool; IGRAPH_CHECK(igraph_vector_bool_resize(value, 1)); VECTOR(*value)[0] = VECTOR(*log)[0]; return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattribute_get_string_graph_attr(const igraph_t *graph, - const char *name, - igraph_strvector_t *value) { +static igraph_error_t igraph_i_cattribute_get_string_graph_attr( + const igraph_t *graph, const char *name, igraph_strvector_t *value +) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t j; + igraph_attribute_record_list_t *gal = &attr->gal; igraph_attribute_record_t *rec; igraph_strvector_t *str; - igraph_bool_t l = igraph_i_cattribute_find(gal, name, &j); - if (!l) { - IGRAPH_ERRORF("The graph attribute '%s' does not exist.", IGRAPH_EINVAL, name); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(gal, name, IGRAPH_ATTRIBUTE_STRING, &rec)); - rec = VECTOR(*gal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_STRING) { - IGRAPH_ERRORF("String graph attribute '%s' expected, got %s.", IGRAPH_EINVAL, name, attribute_type_name(rec->type)); - } - str = (igraph_strvector_t*)rec->value; + str = rec->value.as_strvector; IGRAPH_CHECK(igraph_strvector_resize(value, 1)); IGRAPH_CHECK(igraph_strvector_set(value, 0, igraph_strvector_get(str, 0))); @@ -2633,21 +1678,13 @@ static igraph_error_t igraph_i_cattribute_get_numeric_vertex_attr(const igraph_t igraph_vs_t vs, igraph_vector_t *value) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; + igraph_attribute_record_list_t *val = &attr->val; igraph_attribute_record_t *rec; igraph_vector_t *num; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); - if (!l) { - IGRAPH_ERRORF("The vertex attribute '%s' does not exist.", IGRAPH_EINVAL, name); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(val, name, IGRAPH_ATTRIBUTE_NUMERIC, &rec)); - rec = VECTOR(*val)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_NUMERIC) { - IGRAPH_ERRORF("Numeric vertex attribute '%s' expected, got %s.", IGRAPH_EINVAL, name, attribute_type_name(rec->type)); - } - num = (igraph_vector_t*)rec->value; + num = rec->value.as_vector; if (igraph_vs_is_all(&vs)) { igraph_vector_clear(value); IGRAPH_CHECK(igraph_vector_append(value, num)); @@ -2673,22 +1710,15 @@ static igraph_error_t igraph_i_cattribute_get_bool_vertex_attr(const igraph_t *g igraph_vs_t vs, igraph_vector_bool_t *value) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; + igraph_attribute_record_list_t *val = &attr->val; igraph_vit_t it; - igraph_integer_t i, j, v; + igraph_integer_t i, v; igraph_attribute_record_t *rec; igraph_vector_bool_t *log; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); - if (!l) { - IGRAPH_ERRORF("The vertex attribute '%s' does not exist.", IGRAPH_EINVAL, name); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(val, name, IGRAPH_ATTRIBUTE_BOOLEAN, &rec)); - rec = VECTOR(*val)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_BOOLEAN) { - IGRAPH_ERRORF("Boolean vertex attribute '%s' expected, got %s.", IGRAPH_EINVAL, name, attribute_type_name(rec->type)); - } - log = (igraph_vector_bool_t*)rec->value; + log = rec->value.as_vector_bool; if (igraph_vs_is_all(&vs)) { igraph_vector_bool_clear(value); IGRAPH_CHECK(igraph_vector_bool_append(value, log)); @@ -2712,21 +1742,13 @@ static igraph_error_t igraph_i_cattribute_get_string_vertex_attr(const igraph_t igraph_vs_t vs, igraph_strvector_t *value) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; + igraph_attribute_record_list_t *val = &attr->val; igraph_attribute_record_t *rec; igraph_strvector_t *str; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); - if (!l) { - IGRAPH_ERRORF("The vertex attribute '%s' does not exist.", IGRAPH_EINVAL, name); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(val, name, IGRAPH_ATTRIBUTE_STRING, &rec)); - rec = VECTOR(*val)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_STRING) { - IGRAPH_ERRORF("String vertex attribute '%s' expected, got %s.", IGRAPH_EINVAL, name, attribute_type_name(rec->type)); - } - str = (igraph_strvector_t*)rec->value; + str = rec->value.as_strvector; if (igraph_vs_is_all(&vs)) { igraph_strvector_clear(value); IGRAPH_CHECK(igraph_strvector_append(value, str)); @@ -2748,26 +1770,17 @@ static igraph_error_t igraph_i_cattribute_get_string_vertex_attr(const igraph_t return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattribute_get_numeric_edge_attr(const igraph_t *graph, - const char *name, - igraph_es_t es, - igraph_vector_t *value) { +static igraph_error_t igraph_i_cattribute_get_numeric_edge_attr( + const igraph_t *graph, const char *name, igraph_es_t es, igraph_vector_t *value +) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; + igraph_attribute_record_list_t *eal = &attr->eal; igraph_attribute_record_t *rec; igraph_vector_t *num; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); - if (!l) { - IGRAPH_ERRORF("The edge attribute '%s' does not exist.", IGRAPH_EINVAL, name); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(eal, name, IGRAPH_ATTRIBUTE_NUMERIC, &rec)); - rec = VECTOR(*eal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_NUMERIC) { - IGRAPH_ERRORF("Numeric edge attribute '%s' expected, got %s.", IGRAPH_EINVAL, name, attribute_type_name(rec->type)); - } - num = (igraph_vector_t*)rec->value; + num = rec->value.as_vector; if (igraph_es_is_all(&es)) { igraph_vector_clear(value); IGRAPH_CHECK(igraph_vector_append(value, num)); @@ -2788,26 +1801,18 @@ static igraph_error_t igraph_i_cattribute_get_numeric_edge_attr(const igraph_t * return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattribute_get_string_edge_attr(const igraph_t *graph, - const char *name, - igraph_es_t es, - igraph_strvector_t *value) { +static igraph_error_t igraph_i_cattribute_get_string_edge_attr( + const igraph_t *graph, const char *name, igraph_es_t es, + igraph_strvector_t *value +) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; + igraph_attribute_record_list_t *eal = &attr->eal; igraph_attribute_record_t *rec; igraph_strvector_t *str; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); - if (!l) { - IGRAPH_ERRORF("The edge attribute '%s' does not exist.", IGRAPH_EINVAL, name); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(eal, name, IGRAPH_ATTRIBUTE_STRING, &rec)); - rec = VECTOR(*eal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_STRING) { - IGRAPH_ERRORF("String edge attribute '%s' expected, got %s.", IGRAPH_EINVAL, name, attribute_type_name(rec->type)); - } - str = (igraph_strvector_t*)rec->value; + str = rec->value.as_strvector; if (igraph_es_is_all(&es)) { igraph_strvector_clear(value); IGRAPH_CHECK(igraph_strvector_append(value, str)); @@ -2829,26 +1834,18 @@ static igraph_error_t igraph_i_cattribute_get_string_edge_attr(const igraph_t *g return IGRAPH_SUCCESS; } -static igraph_error_t igraph_i_cattribute_get_bool_edge_attr(const igraph_t *graph, - const char *name, - igraph_es_t es, - igraph_vector_bool_t *value) { +static igraph_error_t igraph_i_cattribute_get_bool_edge_attr( + const igraph_t *graph, const char *name, igraph_es_t es, + igraph_vector_bool_t *value +) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; + igraph_attribute_record_list_t *eal = &attr->eal; igraph_attribute_record_t *rec; igraph_vector_bool_t *log; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); - if (!l) { - IGRAPH_ERRORF("The edge attribute '%s' does not exist.", IGRAPH_EINVAL, name); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_return(eal, name, IGRAPH_ATTRIBUTE_BOOLEAN, &rec)); - rec = VECTOR(*eal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_BOOLEAN) { - IGRAPH_ERRORF("Boolean edge attribute '%s' expected, got %s.", IGRAPH_EINVAL, name, attribute_type_name(rec->type)); - } - log = (igraph_vector_bool_t*)rec->value; + log = rec->value.as_vector_bool; if (igraph_es_is_all(&es)) { igraph_vector_bool_clear(value); IGRAPH_CHECK(igraph_vector_bool_append(value, log)); @@ -2954,21 +1951,17 @@ const igraph_attribute_table_t igraph_cattribute_table = { * Time complexity: O(Ag), the number of graph attributes. */ igraph_real_t igraph_cattribute_GAN(const igraph_t *graph, const char *name) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t j; igraph_attribute_record_t *rec; igraph_vector_t *num; - igraph_bool_t l = igraph_i_cattribute_find(gal, name, &j); - if (!l) { + rec = igraph_i_cattribute_find(&attr->gal, name, IGRAPH_ATTRIBUTE_NUMERIC); + if (!rec) { IGRAPH_WARNINGF("Graph attribute '%s' does not exist, returning default numeric attribute value.", name); return IGRAPH_NAN; } - rec = VECTOR(*gal)[j]; - num = (igraph_vector_t*)rec->value; + num = rec->value.as_vector; return VECTOR(*num)[0]; } @@ -2989,21 +1982,17 @@ igraph_real_t igraph_cattribute_GAN(const igraph_t *graph, const char *name) { * Time complexity: O(Ag), the number of graph attributes. */ igraph_bool_t igraph_cattribute_GAB(const igraph_t *graph, const char *name) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t j; igraph_attribute_record_t *rec; igraph_vector_bool_t *log; - igraph_bool_t l = igraph_i_cattribute_find(gal, name, &j); - if (!l) { + rec = igraph_i_cattribute_find(&attr->gal, name, IGRAPH_ATTRIBUTE_BOOLEAN); + if (!rec) { IGRAPH_WARNINGF("Graph attribute '%s' does not exist, returning default boolean attribute value.", name); return false; } - rec = VECTOR(*gal)[j]; - log = (igraph_vector_bool_t*)rec->value; + log = rec->value.as_vector_bool; return VECTOR(*log)[0]; } @@ -3025,21 +2014,17 @@ igraph_bool_t igraph_cattribute_GAB(const igraph_t *graph, const char *name) { * Time complexity: O(Ag), the number of graph attributes. */ const char *igraph_cattribute_GAS(const igraph_t *graph, const char *name) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t j; igraph_attribute_record_t *rec; igraph_strvector_t *str; - igraph_bool_t l = igraph_i_cattribute_find(gal, name, &j); - if (!l) { + rec = igraph_i_cattribute_find(&attr->gal, name, IGRAPH_ATTRIBUTE_STRING); + if (!rec) { IGRAPH_WARNINGF("Graph attribute '%s' does not exist, returning default string attribute value.", name); return ""; } - rec = VECTOR(*gal)[j]; - str = (igraph_strvector_t*)rec->value; + str = rec->value.as_strvector; return igraph_strvector_get(str, 0); } @@ -3063,19 +2048,16 @@ const char *igraph_cattribute_GAS(const igraph_t *graph, const char *name) { igraph_real_t igraph_cattribute_VAN(const igraph_t *graph, const char *name, igraph_integer_t vid) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; igraph_attribute_record_t *rec; igraph_vector_t *num; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); - if (!l) { + rec = igraph_i_cattribute_find(&attr->val, name, IGRAPH_ATTRIBUTE_NUMERIC); + if (!rec) { IGRAPH_WARNINGF("Vertex attribute '%s' does not exist, returning default numeric attribute value.", name); return IGRAPH_NAN; } - rec = VECTOR(*val)[j]; - num = (igraph_vector_t*)rec->value; + num = rec->value.as_vector; return VECTOR(*num)[vid]; } @@ -3099,19 +2081,16 @@ igraph_real_t igraph_cattribute_VAN(const igraph_t *graph, const char *name, igraph_bool_t igraph_cattribute_VAB(const igraph_t *graph, const char *name, igraph_integer_t vid) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; igraph_attribute_record_t *rec; igraph_vector_bool_t *log; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); - if (!l) { + rec = igraph_i_cattribute_find(&attr->val, name, IGRAPH_ATTRIBUTE_BOOLEAN); + if (!rec) { IGRAPH_WARNINGF("Vertex attribute '%s' does not exist, returning default boolean attribute value.", name); return false; } - rec = VECTOR(*val)[j]; - log = (igraph_vector_bool_t*)rec->value; + log = rec->value.as_vector_bool; return VECTOR(*log)[vid]; } @@ -3137,19 +2116,16 @@ igraph_bool_t igraph_cattribute_VAB(const igraph_t *graph, const char *name, const char *igraph_cattribute_VAS(const igraph_t *graph, const char *name, igraph_integer_t vid) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; igraph_attribute_record_t *rec; igraph_strvector_t *str; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); - if (!l) { + rec = igraph_i_cattribute_find(&attr->val, name, IGRAPH_ATTRIBUTE_STRING); + if (!rec) { IGRAPH_WARNINGF("Vertex attribute '%s' does not exist, returning default string attribute value.", name); return ""; } - rec = VECTOR(*val)[j]; - str = (igraph_strvector_t*)rec->value; + str = rec->value.as_strvector; return igraph_strvector_get(str, vid); } @@ -3173,19 +2149,16 @@ const char *igraph_cattribute_VAS(const igraph_t *graph, const char *name, igraph_real_t igraph_cattribute_EAN(const igraph_t *graph, const char *name, igraph_integer_t eid) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; igraph_attribute_record_t *rec; igraph_vector_t *num; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); - if (!l) { + rec = igraph_i_cattribute_find(&attr->eal, name, IGRAPH_ATTRIBUTE_NUMERIC); + if (!rec) { IGRAPH_WARNINGF("Edge attribute '%s' does not exist, returning default numeric attribute value.", name); return IGRAPH_NAN; } - rec = VECTOR(*eal)[j]; - num = (igraph_vector_t*)rec->value; + num = rec->value.as_vector; return VECTOR(*num)[eid]; } @@ -3209,19 +2182,16 @@ igraph_real_t igraph_cattribute_EAN(const igraph_t *graph, const char *name, igraph_bool_t igraph_cattribute_EAB(const igraph_t *graph, const char *name, igraph_integer_t eid) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; igraph_attribute_record_t *rec; igraph_vector_bool_t *log; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); - if (!l) { + rec = igraph_i_cattribute_find(&attr->eal, name, IGRAPH_ATTRIBUTE_BOOLEAN); + if (!rec) { IGRAPH_WARNINGF("Edge attribute '%s' does not exist, returning default boolean attribute value.", name); return false; } - rec = VECTOR(*eal)[j]; - log = (igraph_vector_bool_t*)rec->value; + log = rec->value.as_vector_bool; return VECTOR(*log)[eid]; } @@ -3247,19 +2217,16 @@ igraph_bool_t igraph_cattribute_EAB(const igraph_t *graph, const char *name, const char *igraph_cattribute_EAS(const igraph_t *graph, const char *name, igraph_integer_t eid) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; igraph_attribute_record_t *rec; igraph_strvector_t *str; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); - if (!l) { + rec = igraph_i_cattribute_find(&attr->eal, name, IGRAPH_ATTRIBUTE_STRING); + if (!rec) { IGRAPH_WARNINGF("Edge attribute '%s' does not exist, returning default string attribute value.", name); return ""; } - rec = VECTOR(*eal)[j]; - str = (igraph_strvector_t*)rec->value; + str = rec->value.as_strvector; return igraph_strvector_get(str, eid); } @@ -3279,9 +2246,7 @@ const char *igraph_cattribute_EAS(const igraph_t *graph, const char *name, igraph_error_t igraph_cattribute_VANV(const igraph_t *graph, const char *name, igraph_vs_t vids, igraph_vector_t *result) { - - return igraph_i_cattribute_get_numeric_vertex_attr(graph, name, vids, - result); + return igraph_i_cattribute_get_numeric_vertex_attr(graph, name, vids, result); } /** @@ -3300,9 +2265,7 @@ igraph_error_t igraph_cattribute_VANV(const igraph_t *graph, const char *name, igraph_error_t igraph_cattribute_VABV(const igraph_t *graph, const char *name, igraph_vs_t vids, igraph_vector_bool_t *result) { - - return igraph_i_cattribute_get_bool_vertex_attr(graph, name, vids, - result); + return igraph_i_cattribute_get_bool_vertex_attr(graph, name, vids, result); } /** @@ -3321,9 +2284,7 @@ igraph_error_t igraph_cattribute_VABV(const igraph_t *graph, const char *name, igraph_error_t igraph_cattribute_EANV(const igraph_t *graph, const char *name, igraph_es_t eids, igraph_vector_t *result) { - - return igraph_i_cattribute_get_numeric_edge_attr(graph, name, eids, - result); + return igraph_i_cattribute_get_numeric_edge_attr(graph, name, eids, result); } /** @@ -3342,9 +2303,7 @@ igraph_error_t igraph_cattribute_EANV(const igraph_t *graph, const char *name, igraph_error_t igraph_cattribute_EABV(const igraph_t *graph, const char *name, igraph_es_t eids, igraph_vector_bool_t *result) { - - return igraph_i_cattribute_get_bool_edge_attr(graph, name, eids, - result); + return igraph_i_cattribute_get_bool_edge_attr(graph, name, eids, result); } /** @@ -3364,9 +2323,7 @@ igraph_error_t igraph_cattribute_EABV(const igraph_t *graph, const char *name, igraph_error_t igraph_cattribute_VASV(const igraph_t *graph, const char *name, igraph_vs_t vids, igraph_strvector_t *result) { - - return igraph_i_cattribute_get_string_vertex_attr(graph, name, vids, - result); + return igraph_i_cattribute_get_string_vertex_attr(graph, name, vids, result); } /** @@ -3386,9 +2343,7 @@ igraph_error_t igraph_cattribute_VASV(const igraph_t *graph, const char *name, igraph_error_t igraph_cattribute_EASV(const igraph_t *graph, const char *name, igraph_es_t eids, igraph_strvector_t *result) { - - return igraph_i_cattribute_get_string_edge_attr(graph, name, eids, - result); + return igraph_i_cattribute_get_string_edge_attr(graph, name, eids, result); } /** @@ -3454,44 +2409,16 @@ igraph_bool_t igraph_cattribute_has_attr(const igraph_t *graph, */ igraph_error_t igraph_cattribute_GAN_set(igraph_t *graph, const char *name, igraph_real_t value) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(gal, name, &j); - - if (l) { - igraph_attribute_record_t *rec = VECTOR(*gal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_NUMERIC) { - IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL); - } else { - igraph_vector_t *num = (igraph_vector_t *)rec->value; - VECTOR(*num)[0] = value; - } - } else { - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_vector_t *num; - if (!rec) { - IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - rec->type = IGRAPH_ATTRIBUTE_NUMERIC; - num = IGRAPH_CALLOC(1, igraph_vector_t); - if (!num) { - IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, num); - IGRAPH_VECTOR_INIT_FINALLY(num, 1); - VECTOR(*num)[0] = value; - rec->value = num; - IGRAPH_CHECK(igraph_vector_ptr_push_back(gal, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + igraph_attribute_record_t *rec; + igraph_vector_t *num; + + IGRAPH_CHECK(igraph_i_cattribute_find_or_create( + &attr->gal, name, IGRAPH_ATTRIBUTE_NUMERIC, 1, &rec + )); + + num = rec->value.as_vector; + VECTOR(*num)[0] = value; return IGRAPH_SUCCESS; } @@ -3512,44 +2439,16 @@ igraph_error_t igraph_cattribute_GAN_set(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_GAB_set(igraph_t *graph, const char *name, igraph_bool_t value) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(gal, name, &j); - - if (l) { - igraph_attribute_record_t *rec = VECTOR(*gal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_BOOLEAN) { - IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL); - } else { - igraph_vector_bool_t *log = (igraph_vector_bool_t *)rec->value; - VECTOR(*log)[0] = value; - } - } else { - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_vector_bool_t *log; - if (!rec) { - IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - rec->type = IGRAPH_ATTRIBUTE_BOOLEAN; - log = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (!log) { - IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, log); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(log, 1); - VECTOR(*log)[0] = value; - rec->value = log; - IGRAPH_CHECK(igraph_vector_ptr_push_back(gal, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + igraph_attribute_record_t *rec; + igraph_vector_bool_t *log; + + IGRAPH_CHECK(igraph_i_cattribute_find_or_create( + &attr->gal, name, IGRAPH_ATTRIBUTE_BOOLEAN, 1, &rec + )); + + log = rec->value.as_vector_bool; + VECTOR(*log)[0] = value; return IGRAPH_SUCCESS; } @@ -3571,44 +2470,16 @@ igraph_error_t igraph_cattribute_GAB_set(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_GAS_set(igraph_t *graph, const char *name, const char *value) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(gal, name, &j); - - if (l) { - igraph_attribute_record_t *rec = VECTOR(*gal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_STRING) { - IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL); - } else { - igraph_strvector_t *str = (igraph_strvector_t*)rec->value; - IGRAPH_CHECK(igraph_strvector_set(str, 0, value)); - } - } else { - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_strvector_t *str; - if (!rec) { - IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - rec->type = IGRAPH_ATTRIBUTE_STRING; - str = IGRAPH_CALLOC(1, igraph_strvector_t); - if (!str) { - IGRAPH_ERROR("Cannot add graph attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, str); - IGRAPH_STRVECTOR_INIT_FINALLY(str, 1); - IGRAPH_CHECK(igraph_strvector_set(str, 0, value)); - rec->value = str; - IGRAPH_CHECK(igraph_vector_ptr_push_back(gal, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + igraph_attribute_record_t *rec; + igraph_strvector_t *str; + + IGRAPH_CHECK(igraph_i_cattribute_find_or_create( + &attr->gal, name, IGRAPH_ATTRIBUTE_STRING, 1, &rec + )); + + str = rec->value.as_strvector; + IGRAPH_CHECK(igraph_strvector_set(str, 0, value)); return IGRAPH_SUCCESS; } @@ -3633,45 +2504,13 @@ igraph_error_t igraph_cattribute_GAS_set(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_VAN_set(igraph_t *graph, const char *name, igraph_integer_t vid, igraph_real_t value) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); - - if (l) { - igraph_attribute_record_t *rec = VECTOR(*val)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_NUMERIC) { - IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL); - } else { - igraph_vector_t *num = (igraph_vector_t*)rec->value; - VECTOR(*num)[vid] = value; - } - } else { - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_vector_t *num; - if (!rec) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - rec->type = IGRAPH_ATTRIBUTE_NUMERIC; - num = IGRAPH_CALLOC(1, igraph_vector_t); - if (!num) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, num); - IGRAPH_VECTOR_INIT_FINALLY(num, igraph_vcount(graph)); - igraph_vector_fill(num, IGRAPH_NAN); - VECTOR(*num)[vid] = value; - rec->value = num; - IGRAPH_CHECK(igraph_vector_ptr_push_back(val, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + igraph_attribute_record_t *rec; + + IGRAPH_CHECK(igraph_i_cattribute_find_or_create( + &attr->val, name, IGRAPH_ATTRIBUTE_NUMERIC, igraph_vcount(graph), &rec + )); + VECTOR(*rec->value.as_vector)[vid] = value; return IGRAPH_SUCCESS; } @@ -3696,45 +2535,13 @@ igraph_error_t igraph_cattribute_VAN_set(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_VAB_set(igraph_t *graph, const char *name, igraph_integer_t vid, igraph_bool_t value) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); - - if (l) { - igraph_attribute_record_t *rec = VECTOR(*val)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_BOOLEAN) { - IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL); - } else { - igraph_vector_bool_t *log = (igraph_vector_bool_t*)rec->value; - VECTOR(*log)[vid] = value; - } - } else { - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_vector_bool_t *log; - if (!rec) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - rec->type = IGRAPH_ATTRIBUTE_BOOLEAN; - log = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (!log) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, log); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(log, igraph_vcount(graph)); - igraph_vector_bool_fill(log, false); - VECTOR(*log)[vid] = value; - rec->value = log; - IGRAPH_CHECK(igraph_vector_ptr_push_back(val, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + igraph_attribute_record_t *rec; + + IGRAPH_CHECK(igraph_i_cattribute_find_or_create( + &attr->val, name, IGRAPH_ATTRIBUTE_BOOLEAN, igraph_vcount(graph), &rec + )); + VECTOR(*rec->value.as_vector_bool)[vid] = value; return IGRAPH_SUCCESS; } @@ -3760,44 +2567,13 @@ igraph_error_t igraph_cattribute_VAB_set(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_VAS_set(igraph_t *graph, const char *name, igraph_integer_t vid, const char *value) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); - - if (l) { - igraph_attribute_record_t *rec = VECTOR(*val)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_STRING) { - IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL); - } else { - igraph_strvector_t *str = (igraph_strvector_t*)rec->value; - IGRAPH_CHECK(igraph_strvector_set(str, vid, value)); - } - } else { - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_strvector_t *str; - if (!rec) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - rec->type = IGRAPH_ATTRIBUTE_STRING; - str = IGRAPH_CALLOC(1, igraph_strvector_t); - if (!str) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, str); - IGRAPH_STRVECTOR_INIT_FINALLY(str, igraph_vcount(graph)); - IGRAPH_CHECK(igraph_strvector_set(str, vid, value)); - rec->value = str; - IGRAPH_CHECK(igraph_vector_ptr_push_back(val, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + igraph_attribute_record_t *rec; + + IGRAPH_CHECK(igraph_i_cattribute_find_or_create( + &attr->val, name, IGRAPH_ATTRIBUTE_STRING, igraph_vcount(graph), &rec + )); + IGRAPH_CHECK(igraph_strvector_set(rec->value.as_strvector, vid, value)); return IGRAPH_SUCCESS; } @@ -3822,45 +2598,13 @@ igraph_error_t igraph_cattribute_VAS_set(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_EAN_set(igraph_t *graph, const char *name, igraph_integer_t eid, igraph_real_t value) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); - - if (l) { - igraph_attribute_record_t *rec = VECTOR(*eal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_NUMERIC) { - IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL); - } else { - igraph_vector_t *num = (igraph_vector_t*)rec->value; - VECTOR(*num)[eid] = value; - } - } else { - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_vector_t *num; - if (!rec) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - rec->type = IGRAPH_ATTRIBUTE_NUMERIC; - num = IGRAPH_CALLOC(1, igraph_vector_t); - if (!num) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, num); - IGRAPH_VECTOR_INIT_FINALLY(num, igraph_ecount(graph)); - igraph_vector_fill(num, IGRAPH_NAN); - VECTOR(*num)[eid] = value; - rec->value = num; - IGRAPH_CHECK(igraph_vector_ptr_push_back(eal, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + igraph_attribute_record_t *rec; + + IGRAPH_CHECK(igraph_i_cattribute_find_or_create( + &attr->eal, name, IGRAPH_ATTRIBUTE_NUMERIC, igraph_ecount(graph), &rec + )); + VECTOR(*rec->value.as_vector)[eid] = value; return IGRAPH_SUCCESS; } @@ -3885,45 +2629,13 @@ igraph_error_t igraph_cattribute_EAN_set(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_EAB_set(igraph_t *graph, const char *name, igraph_integer_t eid, igraph_bool_t value) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); - - if (l) { - igraph_attribute_record_t *rec = VECTOR(*eal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_BOOLEAN) { - IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL); - } else { - igraph_vector_bool_t *log = (igraph_vector_bool_t*)rec->value; - VECTOR(*log)[eid] = value; - } - } else { - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_vector_bool_t *log; - if (!rec) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - rec->type = IGRAPH_ATTRIBUTE_BOOLEAN; - log = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (!log) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, log); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(log, igraph_ecount(graph)); - igraph_vector_bool_fill(log, false); - VECTOR(*log)[eid] = value; - rec->value = log; - IGRAPH_CHECK(igraph_vector_ptr_push_back(eal, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + igraph_attribute_record_t *rec; + + IGRAPH_CHECK(igraph_i_cattribute_find_or_create( + &attr->eal, name, IGRAPH_ATTRIBUTE_BOOLEAN, igraph_ecount(graph), &rec + )); + VECTOR(*rec->value.as_vector_bool)[eid] = value; return IGRAPH_SUCCESS; } @@ -3949,44 +2661,13 @@ igraph_error_t igraph_cattribute_EAB_set(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_EAS_set(igraph_t *graph, const char *name, igraph_integer_t eid, const char *value) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); - - if (l) { - igraph_attribute_record_t *rec = VECTOR(*eal)[j]; - if (rec->type != IGRAPH_ATTRIBUTE_STRING) { - IGRAPH_ERROR("Invalid attribute type", IGRAPH_EINVAL); - } else { - igraph_strvector_t *str = (igraph_strvector_t*)rec->value; - IGRAPH_CHECK(igraph_strvector_set(str, eid, value)); - } - } else { - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_strvector_t *str; - if (!rec) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - rec->type = IGRAPH_ATTRIBUTE_STRING; - str = IGRAPH_CALLOC(1, igraph_strvector_t); - if (!str) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, str); - IGRAPH_STRVECTOR_INIT_FINALLY(str, igraph_ecount(graph)); - IGRAPH_CHECK(igraph_strvector_set(str, eid, value)); - rec->value = str; - IGRAPH_CHECK(igraph_vector_ptr_push_back(eal, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + igraph_attribute_record_t *rec; + + IGRAPH_CHECK(igraph_i_cattribute_find_or_create( + &attr->eal, name, IGRAPH_ATTRIBUTE_STRING, igraph_ecount(graph), &rec + )); + IGRAPH_CHECK(igraph_strvector_set(rec->value.as_strvector, eid, value)); return IGRAPH_SUCCESS; } @@ -4010,52 +2691,20 @@ igraph_error_t igraph_cattribute_EAS_set(igraph_t *graph, const char *name, igraph_error_t igraph_cattribute_VAN_setv(igraph_t *graph, const char *name, const igraph_vector_t *v) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); + igraph_attribute_record_t *rec; + igraph_integer_t nv = igraph_vcount(graph); /* Check length first */ - if (igraph_vector_size(v) != igraph_vcount(graph)) { + if (igraph_vector_size(v) != nv) { IGRAPH_ERROR("Invalid vertex attribute vector length", IGRAPH_EINVAL); } - if (l) { - /* Already present, check type */ - igraph_attribute_record_t *rec = VECTOR(*val)[j]; - igraph_vector_t *num = (igraph_vector_t *)rec->value; - if (rec->type != IGRAPH_ATTRIBUTE_NUMERIC) { - IGRAPH_ERROR("Attribute type mismatch", IGRAPH_EINVAL); - } - igraph_vector_clear(num); - IGRAPH_CHECK(igraph_vector_append(num, v)); - } else { - /* Add it */ - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_vector_t *num; - if (!rec) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->type = IGRAPH_ATTRIBUTE_NUMERIC; - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - num = IGRAPH_CALLOC(1, igraph_vector_t); - if (!num) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, num); - rec->value = num; - IGRAPH_CHECK(igraph_vector_init_copy(num, v)); - IGRAPH_FINALLY(igraph_vector_destroy, num); - IGRAPH_CHECK(igraph_vector_ptr_push_back(val, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_create(&attr->val, name, IGRAPH_ATTRIBUTE_NUMERIC, nv, &rec)); + IGRAPH_CHECK(igraph_vector_update(rec->value.as_vector, v)); return IGRAPH_SUCCESS; } + /** * \function igraph_cattribute_VAB_setv * \brief Set a boolean vertex attribute for all vertices. @@ -4075,49 +2724,16 @@ igraph_error_t igraph_cattribute_VAN_setv(igraph_t *graph, const char *name, igraph_error_t igraph_cattribute_VAB_setv(igraph_t *graph, const char *name, const igraph_vector_bool_t *v) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); + igraph_attribute_record_t *rec; + igraph_integer_t nv = igraph_vcount(graph); /* Check length first */ - if (igraph_vector_bool_size(v) != igraph_vcount(graph)) { + if (igraph_vector_bool_size(v) != nv) { IGRAPH_ERROR("Invalid vertex attribute vector length", IGRAPH_EINVAL); } - if (l) { - /* Already present, check type */ - igraph_attribute_record_t *rec = VECTOR(*val)[j]; - igraph_vector_bool_t *log = (igraph_vector_bool_t *)rec->value; - if (rec->type != IGRAPH_ATTRIBUTE_BOOLEAN) { - IGRAPH_ERROR("Attribute type mismatch", IGRAPH_EINVAL); - } - igraph_vector_bool_clear(log); - IGRAPH_CHECK(igraph_vector_bool_append(log, v)); - } else { - /* Add it */ - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_vector_bool_t *log; - if (!rec) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->type = IGRAPH_ATTRIBUTE_BOOLEAN; - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - log = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (!log) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, log); - rec->value = log; - IGRAPH_CHECK(igraph_vector_bool_init_copy(log, v)); - IGRAPH_FINALLY(igraph_vector_bool_destroy, log); - IGRAPH_CHECK(igraph_vector_ptr_push_back(val, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_create(&attr->val, name, IGRAPH_ATTRIBUTE_BOOLEAN, nv, &rec)); + IGRAPH_CHECK(igraph_vector_bool_update(rec->value.as_vector_bool, v)); return IGRAPH_SUCCESS; } @@ -4140,51 +2756,17 @@ igraph_error_t igraph_cattribute_VAB_setv(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_VAS_setv(igraph_t *graph, const char *name, const igraph_strvector_t *sv) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); + igraph_attribute_record_t *rec; + igraph_integer_t nv = igraph_vcount(graph); /* Check length first */ - if (igraph_strvector_size(sv) != igraph_vcount(graph)) { + if (igraph_strvector_size(sv) != nv) { IGRAPH_ERROR("Invalid vertex attribute vector length", IGRAPH_EINVAL); } - if (l) { - /* Already present, check type */ - igraph_attribute_record_t *rec = VECTOR(*val)[j]; - igraph_strvector_t *str = (igraph_strvector_t *)rec->value; - if (rec->type != IGRAPH_ATTRIBUTE_STRING) { - IGRAPH_ERROR("Attribute type mismatch", IGRAPH_EINVAL); - } - igraph_strvector_clear(str); - IGRAPH_CHECK(igraph_strvector_append(str, sv)); - } else { - /* Add it */ - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_strvector_t *str; - if (!rec) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->type = IGRAPH_ATTRIBUTE_STRING; - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - str = IGRAPH_CALLOC(1, igraph_strvector_t); - if (!str) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, str); - rec->value = str; - IGRAPH_CHECK(igraph_strvector_init_copy(str, sv)); - IGRAPH_FINALLY(igraph_strvector_destroy, str); - IGRAPH_CHECK(igraph_vector_ptr_push_back(val, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_create(&attr->val, name, IGRAPH_ATTRIBUTE_STRING, nv, &rec)); + IGRAPH_CHECK(igraph_strvector_update(rec->value.as_strvector, sv)); return IGRAPH_SUCCESS; } @@ -4206,51 +2788,17 @@ igraph_error_t igraph_cattribute_VAS_setv(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_EAN_setv(igraph_t *graph, const char *name, const igraph_vector_t *v) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); + igraph_attribute_record_t *rec; + igraph_integer_t ne = igraph_ecount(graph); /* Check length first */ - if (igraph_vector_size(v) != igraph_ecount(graph)) { + if (igraph_vector_size(v) != ne) { IGRAPH_ERROR("Invalid edge attribute vector length", IGRAPH_EINVAL); } - if (l) { - /* Already present, check type */ - igraph_attribute_record_t *rec = VECTOR(*eal)[j]; - igraph_vector_t *num = (igraph_vector_t *)rec->value; - if (rec->type != IGRAPH_ATTRIBUTE_NUMERIC) { - IGRAPH_ERROR("Attribute type mismatch", IGRAPH_EINVAL); - } - igraph_vector_clear(num); - IGRAPH_CHECK(igraph_vector_append(num, v)); - } else { - /* Add it */ - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_vector_t *num; - if (!rec) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->type = IGRAPH_ATTRIBUTE_NUMERIC; - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - num = IGRAPH_CALLOC(1, igraph_vector_t); - if (!num) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, num); - rec->value = num; - IGRAPH_CHECK(igraph_vector_init_copy(num, v)); - IGRAPH_FINALLY(igraph_vector_destroy, num); - IGRAPH_CHECK(igraph_vector_ptr_push_back(eal, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_create(&attr->eal, name, IGRAPH_ATTRIBUTE_NUMERIC, ne, &rec)); + IGRAPH_CHECK(igraph_vector_update(rec->value.as_vector, v)); return IGRAPH_SUCCESS; } @@ -4272,51 +2820,17 @@ igraph_error_t igraph_cattribute_EAN_setv(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_EAB_setv(igraph_t *graph, const char *name, const igraph_vector_bool_t *v) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); + igraph_attribute_record_t *rec; + igraph_integer_t ne = igraph_ecount(graph); /* Check length first */ - if (igraph_vector_bool_size(v) != igraph_ecount(graph)) { + if (igraph_vector_bool_size(v) != ne) { IGRAPH_ERROR("Invalid edge attribute vector length", IGRAPH_EINVAL); } - if (l) { - /* Already present, check type */ - igraph_attribute_record_t *rec = VECTOR(*eal)[j]; - igraph_vector_bool_t *log = (igraph_vector_bool_t *)rec->value; - if (rec->type != IGRAPH_ATTRIBUTE_BOOLEAN) { - IGRAPH_ERROR("Attribute type mismatch", IGRAPH_EINVAL); - } - igraph_vector_bool_clear(log); - IGRAPH_CHECK(igraph_vector_bool_append(log, v)); - } else { - /* Add it */ - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_vector_bool_t *log; - if (!rec) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->type = IGRAPH_ATTRIBUTE_BOOLEAN; - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - log = IGRAPH_CALLOC(1, igraph_vector_bool_t); - if (!log) { - IGRAPH_ERROR("Cannot add edge attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, log); - rec->value = log; - IGRAPH_CHECK(igraph_vector_bool_init_copy(log, v)); - IGRAPH_FINALLY(igraph_vector_bool_destroy, log); - IGRAPH_CHECK(igraph_vector_ptr_push_back(eal, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_create(&attr->eal, name, IGRAPH_ATTRIBUTE_BOOLEAN, ne, &rec)); + IGRAPH_CHECK(igraph_vector_bool_update(rec->value.as_vector_bool, v)); return IGRAPH_SUCCESS; } @@ -4339,72 +2853,21 @@ igraph_error_t igraph_cattribute_EAB_setv(igraph_t *graph, const char *name, */ igraph_error_t igraph_cattribute_EAS_setv(igraph_t *graph, const char *name, const igraph_strvector_t *sv) { - igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); + igraph_attribute_record_t *rec; + igraph_integer_t ne = igraph_ecount(graph); /* Check length first */ - if (igraph_strvector_size(sv) != igraph_ecount(graph)) { + if (igraph_strvector_size(sv) != ne) { IGRAPH_ERROR("Invalid edge attribute vector length", IGRAPH_EINVAL); } - if (l) { - /* Already present, check type */ - igraph_attribute_record_t *rec = VECTOR(*eal)[j]; - igraph_strvector_t *str = (igraph_strvector_t *)rec->value; - if (rec->type != IGRAPH_ATTRIBUTE_STRING) { - IGRAPH_ERROR("Attribute type mismatch", IGRAPH_EINVAL); - } - igraph_strvector_clear(str); - IGRAPH_CHECK(igraph_strvector_append(str, sv)); - } else { - /* Add it */ - igraph_attribute_record_t *rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - igraph_strvector_t *str; - if (!rec) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, rec); - rec->type = IGRAPH_ATTRIBUTE_STRING; - rec->name = strdup(name); - if (!rec->name) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, (char*)rec->name); - str = IGRAPH_CALLOC(1, igraph_strvector_t); - if (!str) { - IGRAPH_ERROR("Cannot add vertex attribute", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } - IGRAPH_FINALLY(igraph_free, str); - rec->value = str; - IGRAPH_CHECK(igraph_strvector_init_copy(str, sv)); - IGRAPH_FINALLY(igraph_strvector_destroy, str); - IGRAPH_CHECK(igraph_vector_ptr_push_back(eal, rec)); - IGRAPH_FINALLY_CLEAN(4); - } + IGRAPH_CHECK(igraph_i_cattribute_find_or_create(&attr->eal, name, IGRAPH_ATTRIBUTE_STRING, ne, &rec)); + IGRAPH_CHECK(igraph_strvector_update(rec->value.as_strvector, sv)); return IGRAPH_SUCCESS; } -static void igraph_i_cattribute_free_rec(igraph_attribute_record_t *rec) { - - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *num = (igraph_vector_t*)rec->value; - igraph_vector_destroy(num); - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *str = (igraph_strvector_t*)rec->value; - igraph_strvector_destroy(str); - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *boolvec = (igraph_vector_bool_t*)rec->value; - igraph_vector_bool_destroy(boolvec); - } - IGRAPH_FREE(rec->name); - IGRAPH_FREE(rec->value); - IGRAPH_FREE(rec); -} - /** * \function igraph_cattribute_remove_g * \brief Remove a graph attribute. @@ -4418,13 +2881,11 @@ static void igraph_i_cattribute_free_rec(igraph_attribute_record_t *rec) { void igraph_cattribute_remove_g(igraph_t *graph, const char *name) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(gal, name, &j); + igraph_attribute_record_list_t *gal = &attr->gal; + igraph_integer_t j = igraph_i_cattribute_find_index(gal, name); - if (l) { - igraph_i_cattribute_free_rec(VECTOR(*gal)[j]); - igraph_vector_ptr_remove(gal, j); + if (j >= 0) { + igraph_attribute_record_list_discard(gal, j); } else { IGRAPH_WARNING("Cannot remove non-existent graph attribute"); } @@ -4443,13 +2904,11 @@ void igraph_cattribute_remove_g(igraph_t *graph, const char *name) { void igraph_cattribute_remove_v(igraph_t *graph, const char *name) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(val, name, &j); + igraph_attribute_record_list_t *val = &attr->val; + igraph_integer_t j = igraph_i_cattribute_find_index(val, name); - if (l) { - igraph_i_cattribute_free_rec(VECTOR(*val)[j]); - igraph_vector_ptr_remove(val, j); + if (j >= 0) { + igraph_attribute_record_list_discard(val, j); } else { IGRAPH_WARNING("Cannot remove non-existent graph attribute"); } @@ -4463,18 +2922,15 @@ void igraph_cattribute_remove_v(igraph_t *graph, const char *name) { * \param name Name of the edge attribute to remove. * * \sa \ref DELEA for a simpler way. - * */ void igraph_cattribute_remove_e(igraph_t *graph, const char *name) { igraph_i_cattributes_t *attr = graph->attr; - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t j; - igraph_bool_t l = igraph_i_cattribute_find(eal, name, &j); + igraph_attribute_record_list_t *eal = &attr->eal; + igraph_integer_t j = igraph_i_cattribute_find_index(eal, name); - if (l) { - igraph_i_cattribute_free_rec(VECTOR(*eal)[j]); - igraph_vector_ptr_remove(eal, j); + if (j >= 0) { + igraph_attribute_record_list_discard(eal, j); } else { IGRAPH_WARNING("Cannot remove non-existent graph attribute"); } @@ -4498,27 +2954,12 @@ void igraph_cattribute_remove_all(igraph_t *graph, igraph_bool_t g, igraph_i_cattributes_t *attr = graph->attr; if (g) { - igraph_vector_ptr_t *gal = &attr->gal; - igraph_integer_t i, n = igraph_vector_ptr_size(gal); - for (i = 0; i < n; i++) { - igraph_i_cattribute_free_rec(VECTOR(*gal)[i]); - } - igraph_vector_ptr_clear(gal); + igraph_attribute_record_list_clear(&attr->gal); } if (v) { - igraph_vector_ptr_t *val = &attr->val; - igraph_integer_t i, n = igraph_vector_ptr_size(val); - for (i = 0; i < n; i++) { - igraph_i_cattribute_free_rec(VECTOR(*val)[i]); - } - igraph_vector_ptr_clear(val); + igraph_attribute_record_list_clear(&attr->val); } if (e) { - igraph_vector_ptr_t *eal = &attr->eal; - igraph_integer_t i, n = igraph_vector_ptr_size(eal); - for (i = 0; i < n; i++) { - igraph_i_cattribute_free_rec(VECTOR(*eal)[i]); - } - igraph_vector_ptr_clear(eal); + igraph_attribute_record_list_clear(&attr->eal); } } diff --git a/src/vendor/cigraph/src/graph/iterators.c b/src/vendor/cigraph/src/graph/iterators.c index c82ea990d74..038dff2e132 100644 --- a/src/vendor/cigraph/src/graph/iterators.c +++ b/src/vendor/cigraph/src/graph/iterators.c @@ -1982,7 +1982,7 @@ igraph_error_t igraph_eit_create(const igraph_t *graph, igraph_es_t es, igraph_e eit->start = es.data.eid; eit->end = es.data.eid + 1; if (eit->pos >= igraph_ecount(graph)) { - IGRAPH_ERROR("Cannot create iterator, invalid edge ID.", IGRAPH_EINVAL); + IGRAPH_ERROR("Cannot create iterator.", IGRAPH_EINVEID); } break; case IGRAPH_ES_VECTOR: @@ -1993,7 +1993,7 @@ igraph_error_t igraph_eit_create(const igraph_t *graph, igraph_es_t es, igraph_e eit->vec = es.data.vecptr; eit->end = igraph_vector_int_size(eit->vec); if (!igraph_vector_int_isininterval(eit->vec, 0, igraph_ecount(graph) - 1)) { - IGRAPH_ERROR("Cannot create iterator, invalid edge ID.", IGRAPH_EINVAL); + IGRAPH_ERROR("Cannot create iterator.", IGRAPH_EINVEID); } break; case IGRAPH_ES_RANGE: @@ -2002,10 +2002,10 @@ igraph_error_t igraph_eit_create(const igraph_t *graph, igraph_es_t es, igraph_e if (es.data.range.start < 0 || es.data.range.start > no_of_edges || (no_of_edges > 0 && es.data.range.start == no_of_edges)) { - IGRAPH_ERROR("Cannot create range iterator, starting edge ID out of range.", IGRAPH_EINVAL); + IGRAPH_ERROR("Cannot create range iterator, starting edge ID out of range.", IGRAPH_EINVEID); } if (es.data.range.end < 0 || es.data.range.end > no_of_edges) { - IGRAPH_ERROR("Cannot create range iterator, ending edge ID out of range.", IGRAPH_EINVAL); + IGRAPH_ERROR("Cannot create range iterator, ending edge ID out of range.", IGRAPH_EINVEID); } } eit->type = IGRAPH_EIT_RANGE; diff --git a/src/vendor/cigraph/src/graph/type_common.c b/src/vendor/cigraph/src/graph/type_common.c index da01c834c2e..8293d50278b 100644 --- a/src/vendor/cigraph/src/graph/type_common.c +++ b/src/vendor/cigraph/src/graph/type_common.c @@ -90,7 +90,20 @@ igraph_error_t igraph_empty(igraph_t *graph, igraph_integer_t n, igraph_bool_t d * \example examples/simple/igraph_delete_vertices.c */ igraph_error_t igraph_delete_vertices(igraph_t *graph, const igraph_vs_t vertices) { - return igraph_delete_vertices_idx(graph, vertices, /* idx= */ 0, /* invidx= */ 0); + return igraph_delete_vertices_map(graph, vertices, /* idx= */ 0, /* invidx= */ 0); +} + +/** + * \function igraph_delete_vertices_idx + * \brief Removes some vertices (with all their edges) from the graph (deprecated alias). + * + * \deprecated-by igraph_delete_vertices_map 0.11.0 + */ +igraph_error_t igraph_delete_vertices_idx( + igraph_t *graph, const igraph_vs_t vertices, igraph_vector_int_t *idx, + igraph_vector_int_t *invidx +) { + return igraph_delete_vertices_map(graph, vertices, idx, invidx); } /** @@ -120,7 +133,7 @@ igraph_error_t igraph_edge( ) { if (eid < 0 || eid >= igraph_ecount(graph)) { - IGRAPH_ERROR("Invalid edge ID when retrieving edge endpoints.", IGRAPH_EINVAL); + IGRAPH_ERROR("Cannot retrieve edge endpoints.", IGRAPH_EINVEID); } if (igraph_is_directed(graph)) { diff --git a/src/vendor/cigraph/src/graph/type_indexededgelist.c b/src/vendor/cigraph/src/graph/type_indexededgelist.c index 6380207380e..fbe2a8af22f 100644 --- a/src/vendor/cigraph/src/graph/type_indexededgelist.c +++ b/src/vendor/cigraph/src/graph/type_indexededgelist.c @@ -95,12 +95,17 @@ static igraph_error_t igraph_i_create_start_vectors( * Time complexity: O(|V|) for a graph with * |V| vertices (and no edges). */ -igraph_error_t igraph_empty_attrs(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, void *attr) { +igraph_error_t igraph_empty_attrs( + igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, + const igraph_attribute_record_list_t *attr +) { if (n < 0) { IGRAPH_ERROR("Number of vertices must not be negative.", IGRAPH_EINVAL); } + memset(graph, 0, sizeof(igraph_t)); + graph->n = 0; graph->directed = directed; IGRAPH_VECTOR_INT_INIT_FINALLY(&graph->from, 0); @@ -121,7 +126,6 @@ igraph_error_t igraph_empty_attrs(igraph_t *graph, igraph_integer_t n, igraph_bo VECTOR(graph->is)[0] = 0; /* init attributes */ - graph->attr = 0; IGRAPH_CHECK(igraph_i_attribute_init(graph, attr)); /* add the vertices */ @@ -148,8 +152,7 @@ igraph_error_t igraph_empty_attrs(igraph_t *graph, igraph_integer_t n, igraph_bo * Time complexity: operating system specific. */ void igraph_destroy(igraph_t *graph) { - - IGRAPH_I_ATTRIBUTE_DESTROY(graph); + igraph_i_attribute_destroy(graph); igraph_i_property_cache_destroy(graph->cache); IGRAPH_FREE(graph->cache); @@ -189,6 +192,8 @@ void igraph_destroy(igraph_t *graph) { */ igraph_error_t igraph_copy(igraph_t *to, const igraph_t *from) { + memset(to, 0, sizeof(igraph_t)); + to->n = from->n; to->directed = from->directed; IGRAPH_CHECK(igraph_vector_int_init_copy(&to->from, &from->from)); @@ -210,7 +215,7 @@ igraph_error_t igraph_copy(igraph_t *to, const igraph_t *from) { IGRAPH_CHECK(igraph_i_property_cache_copy(to->cache, from->cache)); IGRAPH_FINALLY(igraph_i_property_cache_destroy, to->cache); - IGRAPH_I_ATTRIBUTE_COPY(to, from, true, true, true); /* does IGRAPH_CHECK */ + IGRAPH_CHECK(igraph_i_attribute_copy(to, from, true, true, true)); IGRAPH_FINALLY_CLEAN(8); return IGRAPH_SUCCESS; @@ -234,7 +239,7 @@ igraph_error_t igraph_copy(igraph_t *to, const igraph_t *from) { * \param attr The attributes of the new edges. You can supply a null pointer * here if you do not need edge attributes. * \return Error code: - * \c IGRAPH_EINVEVECTOR: invalid (odd) edges vector length, + * \c IGRAPH_EINVAL: invalid (odd) edges vector length, * \c IGRAPH_EINVVID: invalid vertex ID in edges vector. * * This function invalidates all iterators. @@ -245,8 +250,10 @@ igraph_error_t igraph_copy(igraph_t *to, const igraph_t *from) { * * \example examples/simple/creation.c */ -igraph_error_t igraph_add_edges(igraph_t *graph, const igraph_vector_int_t *edges, - void *attr) { +igraph_error_t igraph_add_edges( + igraph_t *graph, const igraph_vector_int_t *edges, + const igraph_attribute_record_list_t *attr +) { igraph_integer_t no_of_edges = igraph_vector_int_size(&graph->from); igraph_integer_t edges_to_add = igraph_vector_int_size(edges) / 2; igraph_integer_t new_no_of_edges; @@ -255,7 +262,7 @@ igraph_error_t igraph_add_edges(igraph_t *graph, const igraph_vector_int_t *edge igraph_bool_t directed = igraph_is_directed(graph); if (igraph_vector_int_size(edges) % 2 != 0) { - IGRAPH_ERROR("Invalid (odd) length of edges vector.", IGRAPH_EINVEVECTOR); + IGRAPH_ERROR("Invalid (odd) length of edges vector.", IGRAPH_EINVAL); } if (!igraph_vector_int_isininterval(edges, 0, igraph_vcount(graph) - 1)) { IGRAPH_ERROR("Out-of-range vertex IDs when adding edges.", IGRAPH_EINVVID); @@ -378,7 +385,9 @@ igraph_error_t igraph_add_edges(igraph_t *graph, const igraph_vector_int_t *edge * * \example examples/simple/creation.c */ -igraph_error_t igraph_add_vertices(igraph_t *graph, igraph_integer_t nv, void *attr) { +igraph_error_t igraph_add_vertices( + igraph_t *graph, igraph_integer_t nv, const igraph_attribute_record_list_t *attr +) { igraph_integer_t ec = igraph_ecount(graph); igraph_integer_t vc = igraph_vcount(graph); igraph_integer_t new_vc; @@ -605,7 +614,7 @@ igraph_error_t igraph_delete_edges(igraph_t *graph, igraph_es_t edges) { /** * \ingroup interface - * \function igraph_delete_vertices_idx + * \function igraph_delete_vertices_map * \brief Removes some vertices (with all their edges) from the graph. * * @@ -620,12 +629,10 @@ igraph_error_t igraph_delete_edges(igraph_t *graph, igraph_es_t edges) { * \param graph The graph to work on. * \param vertices The IDs of the vertices to remove, in a vector. The vector * may contain the same ID more than once. - * \param idx An optional pointer to a vector that provides the mapping from + * \param map An optional pointer to a vector that provides the mapping from * the vertex IDs \em before the removal to the vertex IDs \em after - * the removal, \em plus one. Zero is used to represent vertices that were - * removed during the operation. You can supply \c NULL here if you are not - * interested. - * \param invidx An optional pointer to a vector that provides the mapping from + * the removal. You can supply \c NULL here if you are not interested. + * \param invmap An optional pointer to a vector that provides the mapping from * the vertex IDs \em after the removal to the vertex IDs \em before * the removal. You can supply \c NULL here if you are not interested. * \return Error code: @@ -633,12 +640,10 @@ igraph_error_t igraph_delete_edges(igraph_t *graph, igraph_es_t edges) { * * Time complexity: O(|V|+|E|), |V| and |E| are the number of vertices and * edges in the original graph. - * - * \example examples/simple/igraph_delete_vertices.c */ -igraph_error_t igraph_delete_vertices_idx( - igraph_t *graph, const igraph_vs_t vertices, igraph_vector_int_t *idx, - igraph_vector_int_t *invidx +igraph_error_t igraph_delete_vertices_map( + igraph_t *graph, const igraph_vs_t vertices, igraph_vector_int_t *map, + igraph_vector_int_t *invmap ) { igraph_integer_t no_of_edges = igraph_ecount(graph); igraph_integer_t no_of_nodes = igraph_vcount(graph); @@ -649,10 +654,10 @@ igraph_error_t igraph_delete_vertices_idx( igraph_integer_t i, j; igraph_integer_t remaining_vertices, remaining_edges; - if (idx) { - my_vertex_recoding = idx; - IGRAPH_CHECK(igraph_vector_int_resize(idx, no_of_nodes)); - igraph_vector_int_null(idx); + if (map) { + my_vertex_recoding = map; + IGRAPH_CHECK(igraph_vector_int_resize(map, no_of_nodes)); + igraph_vector_int_null(map); } else { IGRAPH_VECTOR_INT_INIT_FINALLY(&vertex_recoding, no_of_nodes); } @@ -673,24 +678,25 @@ igraph_error_t igraph_delete_vertices_idx( /* create vertex recoding vector */ for (remaining_vertices = 0, i = 0; i < no_of_nodes; i++) { if (VECTOR(*my_vertex_recoding)[i] == 0) { - VECTOR(*my_vertex_recoding)[i] = remaining_vertices + 1; + VECTOR(*my_vertex_recoding)[i] = remaining_vertices; remaining_vertices++; } else { - VECTOR(*my_vertex_recoding)[i] = 0; + VECTOR(*my_vertex_recoding)[i] = -1; } } /* create edge recoding vector */ for (remaining_edges = 0, i = 0; i < no_of_edges; i++) { igraph_integer_t from = VECTOR(graph->from)[i]; igraph_integer_t to = VECTOR(graph->to)[i]; - if (VECTOR(*my_vertex_recoding)[from] != 0 && - VECTOR(*my_vertex_recoding)[to ] != 0) { + if (VECTOR(*my_vertex_recoding)[from] >= 0 && + VECTOR(*my_vertex_recoding)[to ] >= 0) { VECTOR(edge_recoding)[i] = remaining_edges + 1; remaining_edges++; } } /* start creating the graph */ + memset(&newgraph, 0, sizeof(igraph_t)); newgraph.n = remaining_vertices; newgraph.directed = graph->directed; @@ -707,8 +713,8 @@ igraph_error_t igraph_delete_vertices_idx( if (VECTOR(edge_recoding)[i] > 0) { igraph_integer_t from = VECTOR(graph->from)[i]; igraph_integer_t to = VECTOR(graph->to )[i]; - VECTOR(newgraph.from)[j] = VECTOR(*my_vertex_recoding)[from] - 1; - VECTOR(newgraph.to )[j] = VECTOR(*my_vertex_recoding)[to] - 1; + VECTOR(newgraph.from)[j] = VECTOR(*my_vertex_recoding)[from]; + VECTOR(newgraph.to )[j] = VECTOR(*my_vertex_recoding)[to]; j++; } } @@ -731,8 +737,9 @@ igraph_error_t igraph_delete_vertices_idx( IGRAPH_FINALLY(igraph_i_property_cache_destroy, newgraph.cache); /* attributes */ - IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, - /*graph=*/ 1, /*vertex=*/0, /*edge=*/0); + IGRAPH_CHECK(igraph_i_attribute_copy( + &newgraph, graph, /* graph= */ true, /* vertex= */ false, /* edge= */ false + )); /* at this point igraph_destroy can take over the responsibility of * deallocating the graph */ @@ -744,13 +751,11 @@ igraph_error_t igraph_delete_vertices_idx( IGRAPH_VECTOR_INT_INIT_FINALLY(&iidx, remaining_vertices); for (i = 0; i < no_of_nodes; i++) { igraph_integer_t jj = VECTOR(*my_vertex_recoding)[i]; - if (jj != 0) { - VECTOR(iidx)[ jj - 1 ] = i; + if (jj >= 0) { + VECTOR(iidx)[ jj ] = i; } } - IGRAPH_CHECK(igraph_i_attribute_permute_vertices(graph, - &newgraph, - &iidx)); + IGRAPH_CHECK(igraph_i_attribute_permute_vertices(graph, &newgraph, &iidx)); IGRAPH_CHECK(igraph_vector_int_resize(&iidx, remaining_edges)); for (i = 0; i < no_of_edges; i++) { igraph_integer_t jj = VECTOR(edge_recoding)[i]; @@ -770,18 +775,17 @@ igraph_error_t igraph_delete_vertices_idx( IGRAPH_FINALLY_CLEAN(3); - /* TODO: this is duplicate */ - if (invidx) { - IGRAPH_CHECK(igraph_vector_int_resize(invidx, remaining_vertices)); + if (invmap) { + IGRAPH_CHECK(igraph_vector_int_resize(invmap, remaining_vertices)); for (i = 0; i < no_of_nodes; i++) { igraph_integer_t newid = VECTOR(*my_vertex_recoding)[i]; - if (newid != 0) { - VECTOR(*invidx)[newid - 1] = i; + if (newid >= 0) { + VECTOR(*invmap)[newid] = i; } } } - if (!idx) { + if (!map) { igraph_vector_int_destroy(my_vertex_recoding); IGRAPH_FINALLY_CLEAN(1); } diff --git a/src/vendor/cigraph/src/hrg/hrg.cc b/src/vendor/cigraph/src/hrg/hrg.cc index ca1697fc98f..e484092011b 100644 --- a/src/vendor/cigraph/src/hrg/hrg.cc +++ b/src/vendor/cigraph/src/hrg/hrg.cc @@ -636,12 +636,9 @@ igraph_error_t igraph_hrg_dendrogram(igraph_t *graph, const igraph_hrg_t *hrg) { const igraph_integer_t no_of_edges = no_of_nodes > 0 ? no_of_nodes - 1 : 0; igraph_vector_int_t edges; igraph_integer_t i, idx = 0; - igraph_vector_ptr_t vattrs; + igraph_attribute_record_list_t vattrs; igraph_vector_t prob; - igraph_attribute_record_t rec = { "probability", - IGRAPH_ATTRIBUTE_NUMERIC, - &prob - }; + igraph_attribute_record_t* rec; // Probability labels, for leaf nodes they are IGRAPH_NAN IGRAPH_VECTOR_INIT_FINALLY(&prob, no_of_nodes); @@ -653,9 +650,13 @@ igraph_error_t igraph_hrg_dendrogram(igraph_t *graph, const igraph_hrg_t *hrg) { } IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_of_edges * 2); - IGRAPH_CHECK(igraph_vector_ptr_init(&vattrs, 1)); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &vattrs); - VECTOR(vattrs)[0] = &rec; + IGRAPH_CHECK(igraph_attribute_record_list_init(&vattrs, 1)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &vattrs); + + rec = igraph_attribute_record_list_get_ptr(&vattrs, 1); + IGRAPH_CHECK(igraph_attribute_record_set_name(rec, "probability")); + IGRAPH_CHECK(igraph_attribute_record_set_type(rec, IGRAPH_ATTRIBUTE_NUMERIC)); + igraph_vector_swap(rec->value.as_vector, &prob); for (i = 0; i < orig_nodes - 1; i++) { igraph_integer_t left = VECTOR(hrg->left)[i]; @@ -672,7 +673,7 @@ igraph_error_t igraph_hrg_dendrogram(igraph_t *graph, const igraph_hrg_t *hrg) { IGRAPH_CHECK(igraph_add_vertices(graph, no_of_nodes, &vattrs)); IGRAPH_CHECK(igraph_add_edges(graph, &edges, NULL)); - igraph_vector_ptr_destroy(&vattrs); + igraph_attribute_record_list_destroy(&vattrs); igraph_vector_int_destroy(&edges); igraph_vector_destroy(&prob); IGRAPH_FINALLY_CLEAN(4); // + 1 for graph diff --git a/src/vendor/cigraph/src/internal/glpk_support.c b/src/vendor/cigraph/src/internal/glpk_support.c index 384390e737d..41f0f50607d 100644 --- a/src/vendor/cigraph/src/internal/glpk_support.c +++ b/src/vendor/cigraph/src/internal/glpk_support.c @@ -49,7 +49,7 @@ int igraph_i_glpk_terminal_hook(void *info, const char *s) { if (igraph_i_interruption_handler && !igraph_i_glpk_error_info.is_interrupted && - igraph_allow_interruption(NULL) != IGRAPH_SUCCESS) { + igraph_allow_interruption() != IGRAPH_SUCCESS) { /* If an interruption has already occurred, do not set another error, to avoid an infinite loop between the term_hook (this function) and the error_hook. */ @@ -90,7 +90,7 @@ void igraph_i_glpk_interruption_hook(glp_tree *tree, void *info) { with the code GLP_ESTOP. */ if (igraph_i_interruption_handler) { - if (igraph_allow_interruption(NULL) != IGRAPH_SUCCESS) { + if (igraph_allow_interruption() != IGRAPH_SUCCESS) { glp_ios_terminate(tree); } } diff --git a/src/vendor/cigraph/src/internal/hacks.h b/src/vendor/cigraph/src/internal/hacks.h index b38bfce873c..fc8cf071435 100644 --- a/src/vendor/cigraph/src/internal/hacks.h +++ b/src/vendor/cigraph/src/internal/hacks.h @@ -63,11 +63,6 @@ __BEGIN_DECLS #endif #endif -/* Magic macro to fail the build if certain condition does not hold. See: - * https://stackoverflow.com/questions/4079243/how-can-i-use-sizeof-in-a-preprocessor-macro - */ -#define IGRAPH_STATIC_ASSERT(condition) ((void)sizeof(char[1 - 2*!(condition)])) - __END_DECLS #endif diff --git a/src/vendor/cigraph/src/internal/utils.c b/src/vendor/cigraph/src/internal/utils.c index 0698e47dfc8..b1553af4195 100644 --- a/src/vendor/cigraph/src/internal/utils.c +++ b/src/vendor/cigraph/src/internal/utils.c @@ -84,7 +84,7 @@ igraph_error_t igraph_i_matrix_subset_vertices( } /* This is O(1) time */ - IGRAPH_CHECK(igraph_matrix_swap(m, &tmp)); + igraph_matrix_swap(m, &tmp); igraph_matrix_destroy(&tmp); igraph_vit_destroy(&tovit); diff --git a/src/vendor/cigraph/src/io/dl.c b/src/vendor/cigraph/src/io/dl.c index 103033fbff9..ec25002608d 100644 --- a/src/vendor/cigraph/src/io/dl.c +++ b/src/vendor/cigraph/src/io/dl.c @@ -70,9 +70,10 @@ igraph_error_t igraph_read_graph_dl(igraph_t *graph, FILE *instream, igraph_integer_t n, n2; const igraph_strvector_t *namevec = 0; - igraph_vector_ptr_t name, weight; - igraph_vector_ptr_t *pname = 0, *pweight = 0; - igraph_attribute_record_t namerec, weightrec; + igraph_attribute_record_list_t name, weight; + igraph_attribute_record_list_t *pname = NULL; + igraph_attribute_record_list_t *pweight = NULL; + igraph_attribute_record_t *namerec, *weightrec; const char *namestr = "name", *weightstr = "weight"; igraph_i_dl_parsedata_t context; @@ -153,24 +154,28 @@ igraph_error_t igraph_read_graph_dl(igraph_t *graph, FILE *instream, namevec = igraph_i_trie_borrow_keys(&context.trie); } if (namevec) { - IGRAPH_CHECK(igraph_vector_ptr_init(&name, 1)); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &name); + IGRAPH_CHECK(igraph_attribute_record_list_init(&name, 1)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &name); + + namerec = igraph_attribute_record_list_get_ptr(&name, 0); + IGRAPH_CHECK(igraph_attribute_record_set_name(namerec, namestr)); + IGRAPH_CHECK(igraph_attribute_record_set_type(namerec, IGRAPH_ATTRIBUTE_STRING)); + IGRAPH_CHECK(igraph_strvector_update(namerec->value.as_strvector, namevec)); + pname = &name; - namerec.name = namestr; - namerec.type = IGRAPH_ATTRIBUTE_STRING; - namerec.value = namevec; - VECTOR(name)[0] = &namerec; } /* Weights */ if (igraph_vector_size(&context.weights) != 0) { - IGRAPH_CHECK(igraph_vector_ptr_init(&weight, 1)); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &weight); + IGRAPH_CHECK(igraph_attribute_record_list_init(&weight, 1)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &weight); + + weightrec = igraph_attribute_record_list_get_ptr(&weight, 0); + IGRAPH_CHECK(igraph_attribute_record_set_name(weightrec, weightstr)); + IGRAPH_CHECK(igraph_attribute_record_set_type(weightrec, IGRAPH_ATTRIBUTE_NUMERIC)); + igraph_vector_swap(weightrec->value.as_vector, &context.weights); + pweight = &weight; - weightrec.name = weightstr; - weightrec.type = IGRAPH_ATTRIBUTE_NUMERIC; - weightrec.value = &context.weights; - VECTOR(weight)[0] = &weightrec; } /* Create graph */ @@ -180,12 +185,12 @@ igraph_error_t igraph_read_graph_dl(igraph_t *graph, FILE *instream, IGRAPH_CHECK(igraph_add_edges(graph, &context.edges, pweight)); if (pweight) { - igraph_vector_ptr_destroy(pweight); + igraph_attribute_record_list_destroy(pweight); IGRAPH_FINALLY_CLEAN(1); } if (pname) { - igraph_vector_ptr_destroy(pname); + igraph_attribute_record_list_destroy(pname); IGRAPH_FINALLY_CLEAN(1); } diff --git a/src/vendor/cigraph/src/io/gml.c b/src/vendor/cigraph/src/io/gml.c index b0fb9622e7d..bf58853bf75 100644 --- a/src/vendor/cigraph/src/io/gml.c +++ b/src/vendor/cigraph/src/io/gml.c @@ -161,35 +161,6 @@ static igraph_error_t entity_decode(const char *src, char **dest, igraph_bool_t return IGRAPH_SUCCESS; } -static void igraph_i_gml_destroy_attrs(igraph_vector_ptr_t **ptr) { - - igraph_vector_ptr_t *vec; - for (igraph_integer_t i = 0; i < 3; i++) { - vec = ptr[i]; - for (igraph_integer_t j = 0; j < igraph_vector_ptr_size(vec); j++) { - igraph_attribute_record_t *atrec = VECTOR(*vec)[j]; - if (atrec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *value = (igraph_vector_t*)atrec->value; - if (value != 0) { - igraph_vector_destroy(value); - IGRAPH_FREE(value); - } - } else if (atrec->type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *value = (igraph_strvector_t*)atrec->value; - if (value != 0) { - igraph_strvector_destroy(value); - IGRAPH_FREE(value); - } - } else { - /* Some empty attribute records may have been created for composite attributes */ - } - IGRAPH_FREE(atrec->name); - IGRAPH_FREE(atrec); - } - igraph_vector_ptr_destroy(vec); - } -} - static igraph_real_t igraph_i_gml_toreal(igraph_gml_tree_t *node, igraph_integer_t pos) { igraph_i_gml_tree_type_t type = igraph_gml_tree_type(node, pos); @@ -262,18 +233,29 @@ void igraph_i_gml_parsedata_destroy(igraph_i_gml_parsedata_t *context) { /* Takes a vector of attribute records and removes those elements * whose type is unspecified, i.e. IGRAPH_ATTRIBUTE_UNSPECIFIED. */ -static void prune_unknown_attributes(igraph_vector_ptr_t *attrs) { - igraph_integer_t i, j; - for (i = 0, j = 0; i < igraph_vector_ptr_size(attrs); i++) { - igraph_attribute_record_t *atrec = VECTOR(*attrs)[i]; +static igraph_error_t prune_unknown_attributes(igraph_attribute_record_list_t *attrs) { + igraph_integer_t i, n; + igraph_vector_int_t to_remove; + + IGRAPH_VECTOR_INT_INIT_FINALLY(&to_remove, 0); + + n = igraph_attribute_record_list_size(attrs); + for (i = 0; i < n; i++) { + igraph_attribute_record_t *atrec = igraph_attribute_record_list_get_ptr(attrs, i); if (atrec->type == IGRAPH_ATTRIBUTE_UNSPECIFIED) { - IGRAPH_FREE(atrec->name); - IGRAPH_FREE(atrec); - } else { - VECTOR(*attrs)[j++] = VECTOR(*attrs)[i]; + IGRAPH_CHECK(igraph_vector_int_push_back(&to_remove, i)); } } - igraph_vector_ptr_resize(attrs, j); /* shrinks */ + + n = igraph_vector_int_size(&to_remove); + for (i = n - 1; i >= 0; i--) { + igraph_attribute_record_list_discard(attrs, VECTOR(to_remove)[i]); + } + + igraph_vector_int_destroy(&to_remove); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; } /* Converts an integer id to an optionally prefixed string id. */ @@ -289,38 +271,39 @@ static const char *strid(igraph_integer_t id, const char *prefix) { static igraph_error_t create_or_update_attribute(const char *name, igraph_i_gml_tree_type_t type, igraph_trie_t *attrnames, - igraph_vector_ptr_t *attrs) { + igraph_attribute_record_list_t *attrs) { igraph_integer_t trieid, triesize = igraph_trie_size(attrnames); + igraph_attribute_type_t desired_type; + IGRAPH_CHECK(igraph_trie_get(attrnames, name, &trieid)); if (trieid == triesize) { /* new attribute */ - igraph_attribute_record_t *atrec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - IGRAPH_CHECK_OOM(atrec, "Cannot read GML file."); - IGRAPH_FINALLY(igraph_free, atrec); - - atrec->name = strdup(name); - IGRAPH_CHECK_OOM(atrec->name, "Cannot read GML file."); - IGRAPH_FINALLY(igraph_free, (char *) atrec->name); + igraph_attribute_record_t atrec; if (type == IGRAPH_I_GML_TREE_INTEGER || type == IGRAPH_I_GML_TREE_REAL) { - atrec->type = IGRAPH_ATTRIBUTE_NUMERIC; + desired_type = IGRAPH_ATTRIBUTE_NUMERIC; } else if (type == IGRAPH_I_GML_TREE_STRING) { - atrec->type = IGRAPH_ATTRIBUTE_STRING; + desired_type = IGRAPH_ATTRIBUTE_STRING; } else { - atrec->type = IGRAPH_ATTRIBUTE_UNSPECIFIED; + desired_type = IGRAPH_ATTRIBUTE_UNSPECIFIED; } - IGRAPH_CHECK(igraph_vector_ptr_push_back(attrs, atrec)); - IGRAPH_FINALLY_CLEAN(2); + + IGRAPH_CHECK(igraph_attribute_record_init(&atrec, name, desired_type)); + IGRAPH_FINALLY(igraph_attribute_record_destroy, &atrec); + IGRAPH_CHECK(igraph_attribute_record_list_push_back(attrs, &atrec)); + IGRAPH_FINALLY_CLEAN(1); /* ownership of 'atrec' taken by 'attrs' */ } else { /* already seen, should we update type? */ - igraph_attribute_record_t *atrec = VECTOR(*attrs)[trieid]; - igraph_attribute_type_t type1 = atrec->type; + igraph_attribute_record_t *atrec = igraph_attribute_record_list_get_ptr(attrs, trieid); + igraph_attribute_type_t existing_type = atrec->type; if (type == IGRAPH_I_GML_TREE_STRING) { - atrec->type = IGRAPH_ATTRIBUTE_STRING; - } else if (type1 == IGRAPH_ATTRIBUTE_UNSPECIFIED) { + if (existing_type != IGRAPH_ATTRIBUTE_STRING) { + IGRAPH_CHECK(igraph_attribute_record_set_type(atrec, IGRAPH_ATTRIBUTE_STRING)); + } + } else if (existing_type == IGRAPH_ATTRIBUTE_UNSPECIFIED) { if (type == IGRAPH_I_GML_TREE_INTEGER || type == IGRAPH_I_GML_TREE_REAL) { - atrec->type = IGRAPH_ATTRIBUTE_NUMERIC; + IGRAPH_CHECK(igraph_attribute_record_set_type(atrec, IGRAPH_ATTRIBUTE_NUMERIC)); } } } @@ -333,34 +316,21 @@ static igraph_error_t create_or_update_attribute(const char *name, * no_of_edges, or 1 for vertex, edge and graph attributes. * The 'kind' parameter can be "vertex", "edge" or "graph", and * is used solely for showing better warning messages. */ -static igraph_error_t allocate_attributes(igraph_vector_ptr_t *attrs, - igraph_integer_t no_of_items, - const char *kind) { - - igraph_integer_t i, n = igraph_vector_ptr_size(attrs); +static igraph_error_t allocate_attributes( + igraph_attribute_record_list_t *attrs, igraph_integer_t no_of_items, + const char *kind +) { + igraph_integer_t i, n = igraph_attribute_record_list_size(attrs); for (i = 0; i < n; i++) { - igraph_attribute_record_t *atrec = VECTOR(*attrs)[i]; - igraph_attribute_type_t type = atrec->type; - if (type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *p = IGRAPH_CALLOC(1, igraph_vector_t); - IGRAPH_CHECK_OOM(p, "Cannot read GML file."); - IGRAPH_FINALLY(igraph_free, p); - IGRAPH_CHECK(igraph_vector_init(p, no_of_items)); - igraph_vector_fill(p, IGRAPH_NAN); /* use NaN as default */ - atrec->value = p; - IGRAPH_FINALLY_CLEAN(1); - } else if (type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *p = IGRAPH_CALLOC(1, igraph_strvector_t); - IGRAPH_CHECK_OOM(p, "Cannot read GML file."); - IGRAPH_FINALLY(igraph_free, p); - IGRAPH_CHECK(igraph_strvector_init(p, no_of_items)); - atrec->value = p; - IGRAPH_FINALLY_CLEAN(1); - } else if (type == IGRAPH_ATTRIBUTE_UNSPECIFIED) { - IGRAPH_WARNINGF("Composite %s attribute '%s' ignored in GML file.", kind, atrec->name); - } else { - /* Must never reach here. */ - IGRAPH_FATAL("Unexpected attribute type."); + igraph_attribute_record_t *atrec = igraph_attribute_record_list_get_ptr(attrs, i); + + /* Ww have unspecified attribute types in the attribute record list at + * this point because we need to keep the same order in the attribute + * record list as it was in the trie that we use to look up an + * attribute record by name. However, we cannot reside unknown attributes + * so we need to take care of this */ + if (atrec->type != IGRAPH_ATTRIBUTE_UNSPECIFIED) { + IGRAPH_CHECK(igraph_attribute_record_resize(atrec, no_of_items)); } } return IGRAPH_SUCCESS; @@ -425,10 +395,8 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { igraph_trie_t vattrnames; igraph_trie_t eattrnames; igraph_trie_t gattrnames; - igraph_vector_ptr_t gattrs = IGRAPH_VECTOR_PTR_NULL, - vattrs = IGRAPH_VECTOR_PTR_NULL, - eattrs = IGRAPH_VECTOR_PTR_NULL; - igraph_vector_ptr_t *attrs[3]; + igraph_attribute_record_list_t gattrs, vattrs, eattrs; + igraph_attribute_record_list_t *attrs[3]; igraph_integer_t edgeptr = 0; igraph_i_gml_parsedata_t context; igraph_bool_t entity_warned = false; /* used to warn at most once about unsupported entities */ @@ -492,10 +460,12 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { } gtree = igraph_gml_tree_get_tree(context.tree, gidx); - IGRAPH_FINALLY(igraph_i_gml_destroy_attrs, attrs); - IGRAPH_CHECK(igraph_vector_ptr_init(&gattrs, 0)); - IGRAPH_CHECK(igraph_vector_ptr_init(&vattrs, 0)); - IGRAPH_CHECK(igraph_vector_ptr_init(&eattrs, 0)); + IGRAPH_CHECK(igraph_attribute_record_list_init(&gattrs, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &gattrs); + IGRAPH_CHECK(igraph_attribute_record_list_init(&vattrs, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &vattrs); + IGRAPH_CHECK(igraph_attribute_record_list_init(&eattrs, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &eattrs); IGRAPH_TRIE_INIT_FINALLY(&trie, 0); IGRAPH_TRIE_INIT_FINALLY(&vattrnames, 0); @@ -686,13 +656,12 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { igraph_attribute_type_t type; igraph_integer_t ai; IGRAPH_CHECK(igraph_trie_get(&vattrnames, aname, &ai)); - atrec = VECTOR(vattrs)[ai]; + atrec = igraph_attribute_record_list_get_ptr(&vattrs, ai); type = atrec->type; if (type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *v = (igraph_vector_t *) atrec->value; - VECTOR(*v)[trie_id] = igraph_i_gml_toreal(node, j); + VECTOR(*atrec->value.as_vector)[trie_id] = igraph_i_gml_toreal(node, j); } else if (type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *v = (igraph_strvector_t *) atrec->value; + igraph_strvector_t *v = atrec->value.as_strvector; const char *value = igraph_i_gml_tostring(node, j); if (needs_coding(value)) { char *value_decoded; @@ -724,13 +693,12 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { igraph_attribute_record_t *atrec; igraph_attribute_type_t type; IGRAPH_CHECK(igraph_trie_get(&eattrnames, aname, &ai)); - atrec = VECTOR(eattrs)[ai]; + atrec = igraph_attribute_record_list_get_ptr(&eattrs, ai); type = atrec->type; if (type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *v = (igraph_vector_t *) atrec->value; - VECTOR(*v)[edgeid] = igraph_i_gml_toreal(edge, j); + VECTOR(*atrec->value.as_vector)[edgeid] = igraph_i_gml_toreal(edge, j); } else if (type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *v = (igraph_strvector_t *) atrec->value; + igraph_strvector_t *v = atrec->value.as_strvector; const char *value = igraph_i_gml_tostring(edge, j); if (needs_coding(value)) { char *value_decoded; @@ -769,13 +737,12 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { igraph_attribute_record_t *atrec; igraph_attribute_type_t type; IGRAPH_CHECK(igraph_trie_get(&gattrnames, name, &ai)); - atrec = VECTOR(gattrs)[ai]; + atrec = igraph_attribute_record_list_get_ptr(&gattrs, ai); type = atrec->type; if (type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *v = (igraph_vector_t *) atrec->value; - VECTOR(*v)[0] = igraph_i_gml_toreal(gtree, i); + VECTOR(*atrec->value.as_vector)[0] = igraph_i_gml_toreal(gtree, i); } else if (type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *v = (igraph_strvector_t *) atrec->value; + igraph_strvector_t *v = atrec->value.as_strvector; const char *value = igraph_i_gml_tostring(gtree, i); if (needs_coding(value)) { char *value_decoded; @@ -793,10 +760,10 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { } } - /* Remove composite attributes */ - prune_unknown_attributes(&vattrs); - prune_unknown_attributes(&eattrs); - prune_unknown_attributes(&gattrs); + /* Remove composite attributes that we cannot represent in igraph */ + IGRAPH_CHECK(prune_unknown_attributes(&vattrs)); + IGRAPH_CHECK(prune_unknown_attributes(&eattrs)); + IGRAPH_CHECK(prune_unknown_attributes(&gattrs)); igraph_trie_destroy(&trie); igraph_trie_destroy(&gattrnames); @@ -811,9 +778,11 @@ igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream) { IGRAPH_FINALLY_CLEAN(1); /* do not destroy 'graph', just pop it from the stack */ igraph_vector_int_destroy(&edges); - igraph_i_gml_destroy_attrs(attrs); + igraph_attribute_record_list_destroy(&eattrs); + igraph_attribute_record_list_destroy(&vattrs); + igraph_attribute_record_list_destroy(&gattrs); igraph_i_gml_parsedata_destroy(&context); - IGRAPH_FINALLY_CLEAN(3); + IGRAPH_FINALLY_CLEAN(5); return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/io/graphml.c b/src/vendor/cigraph/src/io/graphml.c index 2083154d226..23776971329 100644 --- a/src/vendor/cigraph/src/io/graphml.c +++ b/src/vendor/cigraph/src/io/graphml.c @@ -90,17 +90,13 @@ xmlEntityPtr blankEntity = &blankEntityStruct; } while (0) typedef struct igraph_i_graphml_attribute_record_t { - const char *id; /* GraphML id */ + char *id; /* GraphML id */ enum { I_GRAPHML_BOOLEAN, I_GRAPHML_INTEGER, I_GRAPHML_LONG, I_GRAPHML_FLOAT, I_GRAPHML_DOUBLE, I_GRAPHML_STRING, I_GRAPHML_UNKNOWN_TYPE } type; /* GraphML type */ - union { - igraph_real_t as_numeric; - igraph_bool_t as_boolean; - char *as_string; - } default_value; /* Default value of the attribute, if any */ igraph_attribute_record_t record; + igraph_bool_t record_disowned; /* true if ownership of the record was taken over */ } igraph_i_graphml_attribute_record_t; typedef enum { @@ -212,34 +208,16 @@ static igraph_error_t igraph_i_graphml_parse_boolean( } static void igraph_i_graphml_attribute_record_destroy(igraph_i_graphml_attribute_record_t* rec) { - if (rec->record.type == IGRAPH_ATTRIBUTE_NUMERIC) { - if (rec->record.value != 0) { - igraph_vector_destroy((igraph_vector_t*)rec->record.value); - IGRAPH_FREE(rec->record.value); - } - } else if (rec->record.type == IGRAPH_ATTRIBUTE_STRING) { - if (rec->record.value != 0) { - igraph_strvector_destroy((igraph_strvector_t*)rec->record.value); - IGRAPH_FREE(rec->record.value); - } - if (rec->default_value.as_string != 0) { - IGRAPH_FREE(rec->default_value.as_string); - } - } else if (rec->record.type == IGRAPH_ATTRIBUTE_BOOLEAN) { - if (rec->record.value != 0) { - igraph_vector_bool_destroy((igraph_vector_bool_t*)rec->record.value); - IGRAPH_FREE(rec->record.value); - } - } else if (rec->record.type == IGRAPH_ATTRIBUTE_UNSPECIFIED) { - /* no value was set */ + if (!rec->record_disowned) { + igraph_attribute_record_destroy(&rec->record); } + if (rec->id != NULL) { - xmlFree((void *) rec->id); + igraph_free(rec->id); rec->id = NULL; } - if (rec->record.name != 0) { - IGRAPH_FREE(rec->record.name); - } + + memset(rec, 0, sizeof(igraph_i_graphml_attribute_record_t)); } static igraph_error_t igraph_i_graphml_parser_state_init(struct igraph_i_graphml_parser_state* state, igraph_t* graph, igraph_integer_t index) { @@ -410,34 +388,25 @@ static void igraph_i_graphml_sax_handler_start_document(void *state0) { } static igraph_error_t igraph_i_graphml_parser_state_finish_parsing(struct igraph_i_graphml_parser_state *state) { - igraph_integer_t i, l; - igraph_attribute_record_t idrec, eidrec; + igraph_integer_t i; const char *idstr = "id"; igraph_bool_t already_has_vertex_id = false, already_has_edge_id = false; - igraph_vector_ptr_t vattr, eattr, gattr; - igraph_integer_t esize; + igraph_attribute_record_list_t vattr, eattr, gattr; + igraph_attribute_record_t *idrec; IGRAPH_ASSERT(state->successful); /* check that we have found and parsed the graph the user is interested in */ IGRAPH_ASSERT(state->index < 0); - IGRAPH_CHECK(igraph_vector_ptr_init(&vattr, igraph_vector_ptr_size(&state->v_attrs) + 1)); /* +1 for 'id' */ - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &vattr); - igraph_vector_ptr_resize(&vattr, 0); /* will be filled with push_back() */ - - esize = igraph_vector_ptr_size(&state->e_attrs); - if (igraph_strvector_size(&state->edgeids) != 0) { - esize++; - } - IGRAPH_CHECK(igraph_vector_ptr_init(&eattr, esize)); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &eattr); - igraph_vector_ptr_resize(&eattr, 0); /* will be filled with push_back() */ - - IGRAPH_CHECK(igraph_vector_ptr_init(&gattr, igraph_vector_ptr_size(&state->g_attrs))); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &gattr); - igraph_vector_ptr_resize(&gattr, 0); /* will be filled with push_back() */ + IGRAPH_CHECK(igraph_attribute_record_list_init(&vattr, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &vattr); + IGRAPH_CHECK(igraph_attribute_record_list_init(&eattr, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &eattr); + IGRAPH_CHECK(igraph_attribute_record_list_init(&gattr, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &gattr); + /* Add default attribute values for vertices where needed */ for (i = 0; i < igraph_vector_ptr_size(&state->v_attrs); i++) { igraph_i_graphml_attribute_record_t *graphmlrec = VECTOR(state->v_attrs)[i]; @@ -445,131 +414,68 @@ static igraph_error_t igraph_i_graphml_parser_state_finish_parsing(struct igraph /* Check that the name of the vertex attribute is not 'id'. * If it is then we cannot add the complementary 'id' attribute. */ - if (! strcmp(rec->name, idstr)) { + if (!strcmp(rec->name, idstr)) { already_has_vertex_id = 1; } - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *vec = (igraph_vector_t*)rec->value; - igraph_integer_t origsize = igraph_vector_size(vec); - igraph_integer_t nodes = igraph_trie_size(&state->node_trie); - IGRAPH_CHECK(igraph_vector_resize(vec, nodes)); - for (l = origsize; l < nodes; l++) { - VECTOR(*vec)[l] = graphmlrec->default_value.as_numeric; - } - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *strvec = (igraph_strvector_t*)rec->value; - igraph_integer_t origsize = igraph_strvector_size(strvec); - igraph_integer_t nodes = igraph_trie_size(&state->node_trie); - IGRAPH_CHECK(igraph_strvector_resize(strvec, nodes)); - for (l = origsize; l < nodes; l++) { - IGRAPH_CHECK(igraph_strvector_set(strvec, l, graphmlrec->default_value.as_string)); - } - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *boolvec = (igraph_vector_bool_t*)rec->value; - igraph_integer_t origsize = igraph_vector_bool_size(boolvec); - igraph_integer_t nodes = igraph_trie_size(&state->node_trie); - IGRAPH_CHECK(igraph_vector_bool_resize(boolvec, nodes)); - for (l = origsize; l < nodes; l++) { - VECTOR(*boolvec)[l] = graphmlrec->default_value.as_boolean; - } - } else if (rec->type == IGRAPH_ATTRIBUTE_UNSPECIFIED) { - continue; /* skipped attribute */ + if (rec->type != IGRAPH_ATTRIBUTE_UNSPECIFIED) { + IGRAPH_CHECK(igraph_attribute_record_resize(rec, igraph_trie_size(&state->node_trie))); + IGRAPH_CHECK(igraph_attribute_record_list_push_back(&vattr, rec)); + graphmlrec->record_disowned = true; } - igraph_vector_ptr_push_back(&vattr, rec); /* reserved */ } + + /* Add vertex ID attribute if needed */ if (!already_has_vertex_id) { - idrec.name = idstr; - idrec.type = IGRAPH_ATTRIBUTE_STRING; - idrec.value = igraph_i_trie_borrow_keys(&state->node_trie); - igraph_vector_ptr_push_back(&vattr, &idrec); /* reserved */ + IGRAPH_CHECK(igraph_attribute_record_list_push_back_new(&vattr, &idrec)); + IGRAPH_CHECK(igraph_attribute_record_set_name(idrec, idstr)); + IGRAPH_CHECK(igraph_attribute_record_set_type(idrec, IGRAPH_ATTRIBUTE_STRING)); + IGRAPH_CHECK(igraph_strvector_update(idrec->value.as_strvector, igraph_i_trie_borrow_keys(&state->node_trie))); } else { IGRAPH_WARNING("Could not add vertex ids, there is already an 'id' vertex attribute."); } + /* Add default attribute values for edges where needed */ for (i = 0; i < igraph_vector_ptr_size(&state->e_attrs); i++) { igraph_i_graphml_attribute_record_t *graphmlrec = VECTOR(state->e_attrs)[i]; igraph_attribute_record_t *rec = &graphmlrec->record; - if (! strcmp(rec->name, idstr)) { + if (!strcmp(rec->name, idstr)) { already_has_edge_id = 1; } - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *vec = (igraph_vector_t*)rec->value; - igraph_integer_t origsize = igraph_vector_size(vec); - igraph_integer_t edges = igraph_vector_int_size(&state->edgelist) / 2; - IGRAPH_CHECK(igraph_vector_resize(vec, edges)); - for (l = origsize; l < edges; l++) { - VECTOR(*vec)[l] = graphmlrec->default_value.as_numeric; - } - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *strvec = (igraph_strvector_t*)rec->value; - igraph_integer_t origsize = igraph_strvector_size(strvec); - igraph_integer_t edges = igraph_vector_int_size(&state->edgelist) / 2; - IGRAPH_CHECK(igraph_strvector_resize(strvec, edges)); - for (l = origsize; l < edges; l++) { - IGRAPH_CHECK(igraph_strvector_set(strvec, l, graphmlrec->default_value.as_string)); - } - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *boolvec = (igraph_vector_bool_t*)rec->value; - igraph_integer_t origsize = igraph_vector_bool_size(boolvec); - igraph_integer_t edges = igraph_vector_int_size(&state->edgelist) / 2; - IGRAPH_CHECK(igraph_vector_bool_resize(boolvec, edges)); - for (l = origsize; l < edges; l++) { - VECTOR(*boolvec)[l] = graphmlrec->default_value.as_boolean; - } - } else if (rec->type == IGRAPH_ATTRIBUTE_UNSPECIFIED) { - continue; /* skipped attribute */ + if (rec->type != IGRAPH_ATTRIBUTE_UNSPECIFIED) { + IGRAPH_CHECK(igraph_attribute_record_resize(rec, igraph_vector_int_size(&state->edgelist) / 2)); + IGRAPH_CHECK(igraph_attribute_record_list_push_back(&eattr, rec)); + graphmlrec->record_disowned = true; } - igraph_vector_ptr_push_back(&eattr, rec); /* reserved */ } + + /* Add edge ID attribute if needed */ if (igraph_strvector_size(&state->edgeids) != 0) { if (!already_has_edge_id) { - igraph_integer_t origsize = igraph_strvector_size(&state->edgeids); - eidrec.name = idstr; - eidrec.type = IGRAPH_ATTRIBUTE_STRING; - IGRAPH_CHECK(igraph_strvector_resize(&state->edgeids, igraph_vector_int_size(&state->edgelist) / 2)); - for (; origsize < igraph_strvector_size(&state->edgeids); origsize++) { - IGRAPH_CHECK(igraph_strvector_set(&state->edgeids, origsize, "")); - } - eidrec.value = &state->edgeids; - igraph_vector_ptr_push_back(&eattr, &eidrec); /* reserved */ + IGRAPH_CHECK(igraph_attribute_record_list_push_back_new(&eattr, &idrec)); + IGRAPH_CHECK(igraph_attribute_record_set_name(idrec, idstr)); + IGRAPH_CHECK(igraph_attribute_record_set_type(idrec, IGRAPH_ATTRIBUTE_STRING)); + IGRAPH_CHECK(igraph_strvector_update(idrec->value.as_strvector, igraph_i_trie_borrow_keys(&state->node_trie))); + IGRAPH_CHECK(igraph_attribute_record_resize(idrec, igraph_vector_int_size(&state->edgelist) / 2)); } else { IGRAPH_WARNING("Could not add edge ids, there is already an 'id' edge attribute."); } } + /* Add default graph attribute values where needed */ for (i = 0; i < igraph_vector_ptr_size(&state->g_attrs); i++) { igraph_i_graphml_attribute_record_t *graphmlrec = VECTOR(state->g_attrs)[i]; igraph_attribute_record_t *rec = &graphmlrec->record; - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *vec = (igraph_vector_t*)rec->value; - igraph_integer_t origsize = igraph_vector_size(vec); - IGRAPH_CHECK(igraph_vector_resize(vec, 1)); - for (l = origsize; l < 1; l++) { - VECTOR(*vec)[l] = graphmlrec->default_value.as_numeric; - } - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *strvec = (igraph_strvector_t*)rec->value; - igraph_integer_t origsize = igraph_strvector_size(strvec); - IGRAPH_CHECK(igraph_strvector_resize(strvec, 1)); - for (l = origsize; l < 1; l++) { - IGRAPH_CHECK(igraph_strvector_set(strvec, l, graphmlrec->default_value.as_string)); - } - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *boolvec = (igraph_vector_bool_t*)rec->value; - igraph_integer_t origsize = igraph_vector_bool_size(boolvec); - IGRAPH_CHECK(igraph_vector_bool_resize(boolvec, 1)); - for (l = origsize; l < 1; l++) { - VECTOR(*boolvec)[l] = graphmlrec->default_value.as_boolean; - } - } else if (rec->type == IGRAPH_ATTRIBUTE_UNSPECIFIED) { - continue; /* skipped attribute */ + + if (rec->type != IGRAPH_ATTRIBUTE_UNSPECIFIED) { + IGRAPH_CHECK(igraph_attribute_record_resize(rec, 1)); + IGRAPH_CHECK(igraph_attribute_record_list_push_back(&gattr, rec)); + graphmlrec->record_disowned = true; } - igraph_vector_ptr_push_back(&gattr, rec); /* reserved */ } IGRAPH_CHECK(igraph_empty_attrs(state->g, 0, state->edges_directed, &gattr)); @@ -578,9 +484,9 @@ static igraph_error_t igraph_i_graphml_parser_state_finish_parsing(struct igraph IGRAPH_CHECK(igraph_add_edges(state->g, &state->edgelist, &eattr)); IGRAPH_FINALLY_CLEAN(1); /* graph construction completed successfully */ - igraph_vector_ptr_destroy(&vattr); - igraph_vector_ptr_destroy(&eattr); - igraph_vector_ptr_destroy(&gattr); + igraph_attribute_record_list_destroy(&vattr); + igraph_attribute_record_list_destroy(&eattr); + igraph_attribute_record_list_destroy(&gattr); IGRAPH_FINALLY_CLEAN(3); return IGRAPH_SUCCESS; @@ -595,6 +501,34 @@ static igraph_error_t igraph_i_graphml_parser_state_finish_parsing(struct igraph #define XML_ATTR_VALUE(it) *(it+3), (int)((*(it+4))-(*(it+3))) #define XML_ATTR_VALUE_PF(it) (int)((*(it+4))-(*(it+3))), *(it+3) /* for use in printf-style function with "%.*s" */ +static igraph_error_t safely_convert_xml_attribute_to_string(xmlChar** it, char** str) { + /* This is quite convoluted but we need to go safely from xmlChar*-world + * to char*-world */ + xmlChar *xml_str; + char *c_str; + + xml_str = xmlStrndup(XML_ATTR_VALUE(it)); + IGRAPH_CHECK_OOM(xml_str, "Insufficient memory to duplicate attribute value."); + IGRAPH_FINALLY(xmlFree, xml_str); + + c_str = strdup(fromXmlChar(xml_str)); + IGRAPH_CHECK_OOM(c_str, "Insufficient memory to duplicate attribute value."); + + *str = c_str; + + xmlFree(xml_str); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + +static void safely_free_optional_string(char** str) { + if (*str != NULL) { + igraph_free(*str); + *str = NULL; + } +} + static igraph_bool_t xmlAttrValueEqual(xmlChar** attr, const char* expected) { size_t expected_length = strlen(expected); return ( @@ -623,27 +557,30 @@ static igraph_error_t igraph_i_graphml_add_attribute_key( xmlChar **it; xmlChar *localname; - xmlChar *xmlStr; igraph_trie_t *trie = NULL; igraph_vector_ptr_t *ptrvector = NULL; igraph_integer_t i, n; igraph_integer_t id; igraph_i_graphml_attribute_record_t *rec = NULL; + char *attr_name; + igraph_attribute_type_t igraph_attr_type; igraph_bool_t skip = false; + attr_name = NULL; + IGRAPH_FINALLY(safely_free_optional_string, &attr_name); + if (!state->successful) { /* Parser is already in an error state */ goto exit; } rec = IGRAPH_CALLOC(1, igraph_i_graphml_attribute_record_t); - if (rec == NULL) { - IGRAPH_ERROR("Cannot allocate attribute record.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } + IGRAPH_CHECK_OOM(rec, "Insufficient memory to allocate attribute record."); IGRAPH_FINALLY(igraph_free, rec); IGRAPH_FINALLY(igraph_i_graphml_attribute_record_destroy, rec); + memset(rec, 0, sizeof(igraph_i_graphml_attribute_record_t)); - rec->type = I_GRAPHML_UNKNOWN_TYPE; + igraph_attr_type = IGRAPH_ATTRIBUTE_UNSPECIFIED; for (i = 0, it = (xmlChar**)attrs; i < nb_attrs; i++, it += 5) { if (XML_ATTR_URI(it) != 0 && @@ -654,42 +591,29 @@ static igraph_error_t igraph_i_graphml_add_attribute_key( localname = XML_ATTR_LOCALNAME(it); if (xmlStrEqual(localname, toXmlChar("id"))) { - xmlStr = xmlStrndup(XML_ATTR_VALUE(it)); - IGRAPH_CHECK_OOM(xmlStr, "Cannot duplicate value of 'id' attribute."); - rec->id = fromXmlChar(xmlStr); - xmlStr = NULL; + IGRAPH_CHECK(safely_convert_xml_attribute_to_string(it, &rec->id)); } else if (xmlStrEqual(localname, toXmlChar("attr.name"))) { - xmlStr = xmlStrndup(XML_ATTR_VALUE(it)); - IGRAPH_CHECK_OOM(xmlStr, "Cannot duplicate value of 'attr.name' attribute."); - rec->record.name = fromXmlChar(xmlStr); - xmlStr = NULL; + safely_free_optional_string(&attr_name); + IGRAPH_CHECK(safely_convert_xml_attribute_to_string(it, &attr_name)); } else if (xmlStrEqual(localname, toXmlChar("attr.type"))) { if (xmlAttrValueEqual(it, "boolean")) { + igraph_attr_type = IGRAPH_ATTRIBUTE_BOOLEAN; rec->type = I_GRAPHML_BOOLEAN; - rec->record.type = IGRAPH_ATTRIBUTE_BOOLEAN; - rec->default_value.as_boolean = 0; } else if (xmlAttrValueEqual(it, "string")) { - char *str = strdup(""); - IGRAPH_CHECK_OOM(str, "Cannot allocate new empty string."); + igraph_attr_type = IGRAPH_ATTRIBUTE_STRING; rec->type = I_GRAPHML_STRING; - rec->record.type = IGRAPH_ATTRIBUTE_STRING; - rec->default_value.as_string = str; } else if (xmlAttrValueEqual(it, "float")) { + igraph_attr_type = IGRAPH_ATTRIBUTE_NUMERIC; rec->type = I_GRAPHML_FLOAT; - rec->record.type = IGRAPH_ATTRIBUTE_NUMERIC; - rec->default_value.as_numeric = IGRAPH_NAN; } else if (xmlAttrValueEqual(it, "double")) { + igraph_attr_type = IGRAPH_ATTRIBUTE_NUMERIC; rec->type = I_GRAPHML_DOUBLE; - rec->record.type = IGRAPH_ATTRIBUTE_NUMERIC; - rec->default_value.as_numeric = IGRAPH_NAN; } else if (xmlAttrValueEqual(it, "int")) { + igraph_attr_type = IGRAPH_ATTRIBUTE_NUMERIC; rec->type = I_GRAPHML_INTEGER; - rec->record.type = IGRAPH_ATTRIBUTE_NUMERIC; - rec->default_value.as_numeric = IGRAPH_NAN; } else if (xmlAttrValueEqual(it, "long")) { + igraph_attr_type = IGRAPH_ATTRIBUTE_NUMERIC; rec->type = I_GRAPHML_LONG; - rec->record.type = IGRAPH_ATTRIBUTE_NUMERIC; - rec->default_value.as_numeric = IGRAPH_NAN; } else { IGRAPH_ERRORF("Unknown attribute type '%.*s'.", IGRAPH_PARSEERROR, XML_ATTR_VALUE_PF(it)); @@ -739,9 +663,11 @@ static igraph_error_t igraph_i_graphml_add_attribute_key( } /* in case of a missing attr.name attribute, use the id as the attribute name */ - if (rec->record.name == NULL) { - rec->record.name = strdup(rec->id); - IGRAPH_CHECK_OOM(rec->record.name, "Cannot duplicate attribute ID as name."); + if (attr_name == NULL) { + /* Allocation here is protected by safely_free_optional_string(&attr_name), + * which is already in the finally stack */ + attr_name = strdup(rec->id); + IGRAPH_CHECK_OOM(attr_name, "Cannot duplicate attribute ID as name."); } /* if the attribute type is missing, ignore the attribute with a warning */ @@ -750,9 +676,10 @@ static igraph_error_t igraph_i_graphml_add_attribute_key( skip = 1; } - /* if the value of the 'for' attribute was unknown, throw an error */ + /* if the value of the 'for' attribute was missing, ignore the attribute with a warning */ if (!skip && trie == 0) { - IGRAPH_ERROR("Missing 'for' attribute in a tag.", IGRAPH_PARSEERROR); + IGRAPH_WARNINGF("Ignoring because of a missing 'for' attribute.", rec->id); + skip = 1; } /* If attribute is skipped, proceed according to the type of the associated graph element. */ @@ -770,7 +697,7 @@ static igraph_error_t igraph_i_graphml_add_attribute_key( /* If the skipped attribute was for a supported graph element, we add it * as "UNSPECIFIED" so that we can avoid reporting "unknown attribute" warnings * later. */ - rec->record.type = IGRAPH_ATTRIBUTE_UNSPECIFIED; + igraph_attr_type = IGRAPH_ATTRIBUTE_UNSPECIFIED; } } @@ -784,12 +711,12 @@ static igraph_error_t igraph_i_graphml_add_attribute_key( n = igraph_vector_ptr_size(ptrvector); for (i = 0; i < n; i++) { if (!strcmp( - rec->record.name, + attr_name, ((igraph_i_graphml_attribute_record_t*) igraph_vector_ptr_get(ptrvector, i))->record.name )) { IGRAPH_ERRORF( "Duplicate attribute name found: '%s' (for ).", - IGRAPH_PARSEERROR, rec->record.name, rec->id + IGRAPH_PARSEERROR, attr_name, rec->id ); } } @@ -803,42 +730,12 @@ static igraph_error_t igraph_i_graphml_add_attribute_key( IGRAPH_FINALLY_CLEAN(2); /* create the attribute values */ - switch (rec->record.type) { - igraph_vector_t *vec; - igraph_vector_bool_t *boolvec; - igraph_strvector_t *strvec; - case IGRAPH_ATTRIBUTE_BOOLEAN: - boolvec = IGRAPH_CALLOC(1, igraph_vector_bool_t); - IGRAPH_CHECK_OOM(boolvec, "Cannot allocate value vector for Boolean attribute."); - IGRAPH_FINALLY(igraph_free, boolvec); - IGRAPH_CHECK(igraph_vector_bool_init(boolvec, 0)); - rec->record.value = boolvec; - IGRAPH_FINALLY_CLEAN(1); - break; - case IGRAPH_ATTRIBUTE_NUMERIC: - vec = IGRAPH_CALLOC(1, igraph_vector_t); - IGRAPH_CHECK_OOM(vec, "Cannot allocate value vector for numeric attribute."); - IGRAPH_FINALLY(igraph_free, vec); - IGRAPH_CHECK(igraph_vector_init(vec, 0)); - rec->record.value = vec; - IGRAPH_FINALLY_CLEAN(1); - break; - case IGRAPH_ATTRIBUTE_STRING: - strvec = IGRAPH_CALLOC(1, igraph_strvector_t); - IGRAPH_CHECK_OOM(strvec, "Cannot allocate value vector for string attribute."); - IGRAPH_FINALLY(igraph_free, strvec); - IGRAPH_CHECK(igraph_strvector_init(strvec, 0)); - rec->record.value = strvec; - IGRAPH_FINALLY_CLEAN(1); - break; - case IGRAPH_ATTRIBUTE_UNSPECIFIED: - rec->record.value = NULL; - break; - default: - IGRAPH_FATAL("Unexpected attribute type."); - } + IGRAPH_CHECK(igraph_attribute_record_init(&rec->record, attr_name, igraph_attr_type)); exit: + safely_free_optional_string(&attr_name); + IGRAPH_FINALLY_CLEAN(1); + *record = rec; return IGRAPH_SUCCESS; } @@ -961,55 +858,35 @@ static igraph_error_t igraph_i_graphml_attribute_data_finish(struct igraph_i_gra graphmlrec = VECTOR(*ptrvector)[recid]; rec = &graphmlrec->record; + if (id >= igraph_attribute_record_size(rec) && rec->type != IGRAPH_ATTRIBUTE_UNSPECIFIED) { + IGRAPH_CHECK(igraph_attribute_record_resize(rec, id + 1)); + } + switch (rec->type) { igraph_vector_bool_t *boolvec; igraph_vector_t *vec; igraph_strvector_t *strvec; - igraph_integer_t s, i; const char* strvalue; case IGRAPH_ATTRIBUTE_BOOLEAN: - boolvec = (igraph_vector_bool_t *)rec->value; - s = igraph_vector_bool_size(boolvec); - if (id >= s) { - IGRAPH_CHECK(igraph_vector_bool_resize(boolvec, id + 1)); - for (i = s; i < id; i++) { - VECTOR(*boolvec)[i] = graphmlrec->default_value.as_boolean; - } - } + boolvec = rec->value.as_vector_bool; IGRAPH_CHECK(igraph_i_graphml_parse_boolean( - state->data_char, VECTOR(*boolvec) + id, graphmlrec->default_value.as_boolean + state->data_char, VECTOR(*boolvec) + id, rec->default_value.boolean )); break; case IGRAPH_ATTRIBUTE_NUMERIC: - vec = (igraph_vector_t *)rec->value; - s = igraph_vector_size(vec); - if (id >= s) { - IGRAPH_CHECK(igraph_vector_resize(vec, id + 1)); - for (i = s; i < id; i++) { - VECTOR(*vec)[i] = graphmlrec->default_value.as_numeric; - } - } + vec = rec->value.as_vector; IGRAPH_CHECK(igraph_i_graphml_parse_numeric( - state->data_char, VECTOR(*vec) + id, - graphmlrec->default_value.as_numeric + state->data_char, VECTOR(*vec) + id, rec->default_value.numeric )); break; case IGRAPH_ATTRIBUTE_STRING: - strvec = (igraph_strvector_t *)rec->value; - s = igraph_strvector_size(strvec); - if (id >= s) { - IGRAPH_CHECK(igraph_strvector_resize(strvec, id + 1)); - strvalue = graphmlrec->default_value.as_string; - for (i = s; i < id; i++) { - IGRAPH_CHECK(igraph_strvector_set(strvec, i, strvalue)); - } - } + strvec = rec->value.as_strvector; if (state->data_char) { strvalue = state->data_char; } else { - strvalue = graphmlrec->default_value.as_string; + strvalue = rec->default_value.string; } - IGRAPH_CHECK(igraph_strvector_set(strvec, id, strvalue)); + IGRAPH_CHECK(igraph_strvector_set(strvec, id, strvalue ? strvalue : "")); break; case IGRAPH_ATTRIBUTE_UNSPECIFIED: break; @@ -1028,8 +905,10 @@ static igraph_error_t igraph_i_graphml_attribute_data_finish(struct igraph_i_gra static igraph_error_t igraph_i_graphml_attribute_default_value_finish(struct igraph_i_graphml_parser_state *state) { igraph_i_graphml_attribute_record_t *graphmlrec = state->current_attr_record; + igraph_attribute_record_t *rec; igraph_error_t result = IGRAPH_SUCCESS; - char* str = 0; + igraph_real_t default_num; + igraph_bool_t default_bool; IGRAPH_ASSERT(state->current_attr_record != NULL); @@ -1037,26 +916,19 @@ static igraph_error_t igraph_i_graphml_attribute_default_value_finish(struct igr return IGRAPH_SUCCESS; } - switch (graphmlrec->record.type) { + rec = &graphmlrec->record; + + switch (rec->type) { case IGRAPH_ATTRIBUTE_BOOLEAN: - IGRAPH_CHECK(igraph_i_graphml_parse_boolean( - state->data_char, &graphmlrec->default_value.as_boolean, 0 - )); + IGRAPH_CHECK(igraph_i_graphml_parse_boolean(state->data_char, &default_bool, false)); + IGRAPH_CHECK(igraph_attribute_record_set_default_boolean(rec, default_bool)); break; case IGRAPH_ATTRIBUTE_NUMERIC: - IGRAPH_CHECK(igraph_i_graphml_parse_numeric( - state->data_char, &graphmlrec->default_value.as_numeric, IGRAPH_NAN - )); + IGRAPH_CHECK(igraph_i_graphml_parse_numeric(state->data_char, &default_num, IGRAPH_NAN)); + IGRAPH_CHECK(igraph_attribute_record_set_default_numeric(rec, default_num)); break; case IGRAPH_ATTRIBUTE_STRING: - str = strdup(state->data_char); - IGRAPH_CHECK_OOM(str, "Cannot allocate memory for string attribute."); - - if (graphmlrec->default_value.as_string != 0) { - IGRAPH_FREE(graphmlrec->default_value.as_string); - } - graphmlrec->default_value.as_string = str; - str = NULL; + IGRAPH_CHECK(igraph_attribute_record_set_default_string(rec, state->data_char)); break; case IGRAPH_ATTRIBUTE_UNSPECIFIED: break; @@ -1516,9 +1388,7 @@ static igraph_error_t igraph_i_xml_escape(const char* src, char** dest) { } } *dest = IGRAPH_CALLOC(destlen + 1, char); - if (!*dest) { - IGRAPH_ERROR("Not enough memory.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */ - } + IGRAPH_CHECK_OOM(*dest, "Insufficient memory."); for (s = src, d = *dest; *s; s++, d++) { ch = (unsigned char)(*s); switch (ch) { diff --git a/src/vendor/cigraph/src/io/leda.c b/src/vendor/cigraph/src/io/leda.c index cf742cdde62..51e2cd9380c 100644 --- a/src/vendor/cigraph/src/io/leda.c +++ b/src/vendor/cigraph/src/io/leda.c @@ -84,7 +84,7 @@ igraph_error_t igraph_write_graph_leda(const igraph_t *graph, FILE *outstream, vertex_attr_name = NULL; } if (vertex_attr_name) { - IGRAPH_CHECK(igraph_i_attribute_gettype(graph, &vertex_attr_type, + IGRAPH_CHECK(igraph_i_attribute_get_type(graph, &vertex_attr_type, IGRAPH_ATTRIBUTE_VERTEX, vertex_attr_name)); if (vertex_attr_type != IGRAPH_ATTRIBUTE_NUMERIC && vertex_attr_type != IGRAPH_ATTRIBUTE_STRING && @@ -104,7 +104,7 @@ igraph_error_t igraph_write_graph_leda(const igraph_t *graph, FILE *outstream, edge_attr_name = NULL; } if (edge_attr_name) { - IGRAPH_CHECK(igraph_i_attribute_gettype(graph, &edge_attr_type, + IGRAPH_CHECK(igraph_i_attribute_get_type(graph, &edge_attr_type, IGRAPH_ATTRIBUTE_EDGE, edge_attr_name)); if (edge_attr_type != IGRAPH_ATTRIBUTE_NUMERIC && edge_attr_type != IGRAPH_ATTRIBUTE_STRING && diff --git a/src/vendor/cigraph/src/io/lgl-parser.y b/src/vendor/cigraph/src/io/lgl-parser.y index 792bbbfab28..5d439f3ff7e 100644 --- a/src/vendor/cigraph/src/io/lgl-parser.y +++ b/src/vendor/cigraph/src/io/lgl-parser.y @@ -103,7 +103,7 @@ edges : /* empty */ | edges edge ; edge : edgeid NEWLINE { IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, context->actvertex)); IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, $1)); - IGRAPH_YY_CHECK(igraph_vector_push_back(context->weights, 0)); + IGRAPH_YY_CHECK(igraph_vector_push_back(context->weights, 1.0)); } | edgeid weight NEWLINE { IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, context->actvertex)); diff --git a/src/vendor/cigraph/src/io/lgl.c b/src/vendor/cigraph/src/io/lgl.c index 37c6d7e2b17..7b9f072f632 100644 --- a/src/vendor/cigraph/src/io/lgl.c +++ b/src/vendor/cigraph/src/io/lgl.c @@ -77,10 +77,11 @@ vertex3name [optionalWeight] \endverbatim * graph as an edge attribute called \quote weight\endquote. * \c IGRAPH_ADD_WEIGHTS_YES adds the weights (even if they * are not present in the file, in this case they are assumed - * to be zero). \c IGRAPH_ADD_WEIGHTS_NO does not add any + * to be 1). \c IGRAPH_ADD_WEIGHTS_NO does not add any * edge attribute. \c IGRAPH_ADD_WEIGHTS_IF_PRESENT adds the * attribute if and only if there is at least one explicit - * edge weight in the input file. + * edge weight in the input file, and edges without an explicit + * weight are assumed to have a weight of 1. * \param directed Whether to create a directed graph. As this format * was originally used only for undirected graphs there is no * information in the file about the directedness of the graph. @@ -109,9 +110,9 @@ igraph_error_t igraph_read_graph_lgl(igraph_t *graph, FILE *instream, igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; igraph_vector_t ws = IGRAPH_VECTOR_NULL; igraph_trie_t trie = IGRAPH_TRIE_NULL; - igraph_vector_ptr_t name, weight; - igraph_vector_ptr_t *pname = 0, *pweight = 0; - igraph_attribute_record_t namerec, weightrec; + igraph_attribute_record_list_t name, weight; + igraph_attribute_record_list_t *pname = NULL, *pweight = NULL; + igraph_attribute_record_t *namerec, *weightrec; const char *namestr = "name", *weightstr = "weight"; igraph_i_lgl_parsedata_t context; @@ -159,27 +160,30 @@ igraph_error_t igraph_read_graph_lgl(igraph_t *graph, FILE *instream, IGRAPH_FATALF("Parser returned unexpected error code (%d) when reading LGL file.", err); } - /* Prepare attributes, if needed */ - + /* Prepare attributes if needed */ if (names) { - IGRAPH_CHECK(igraph_vector_ptr_init(&name, 1)); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &name); + IGRAPH_CHECK(igraph_attribute_record_list_init(&name, 1)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &name); + + namerec = igraph_attribute_record_list_get_ptr(&name, 0); + IGRAPH_CHECK(igraph_attribute_record_set_name(namerec, namestr)); + IGRAPH_CHECK(igraph_attribute_record_set_type(namerec, IGRAPH_ATTRIBUTE_STRING)); + IGRAPH_CHECK(igraph_strvector_update( + namerec->value.as_strvector, igraph_i_trie_borrow_keys(context.trie)) + ); + pname = &name; - namerec.name = namestr; - namerec.type = IGRAPH_ATTRIBUTE_STRING; - namerec.value = igraph_i_trie_borrow_keys(&trie); - VECTOR(name)[0] = &namerec; } if (weights == IGRAPH_ADD_WEIGHTS_YES || (weights == IGRAPH_ADD_WEIGHTS_IF_PRESENT && context.has_weights)) { - IGRAPH_CHECK(igraph_vector_ptr_init(&weight, 1)); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &weight); - pweight = &weight; - weightrec.name = weightstr; - weightrec.type = IGRAPH_ATTRIBUTE_NUMERIC; - weightrec.value = &ws; - VECTOR(weight)[0] = &weightrec; + IGRAPH_CHECK(igraph_attribute_record_list_init(&weight, 1)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &weight); + + weightrec = igraph_attribute_record_list_get_ptr(&weight, 0); + IGRAPH_CHECK(igraph_attribute_record_set_name(weightrec, weightstr)); + IGRAPH_CHECK(igraph_attribute_record_set_type(weightrec, IGRAPH_ATTRIBUTE_NUMERIC)); + igraph_vector_swap(weightrec->value.as_vector, context.weights); } /* Create graph */ @@ -189,11 +193,11 @@ igraph_error_t igraph_read_graph_lgl(igraph_t *graph, FILE *instream, IGRAPH_CHECK(igraph_add_edges(graph, &edges, pweight)); if (pweight) { - igraph_vector_ptr_destroy(pweight); + igraph_attribute_record_list_destroy(pweight); IGRAPH_FINALLY_CLEAN(1); } if (pname) { - igraph_vector_ptr_destroy(pname); + igraph_attribute_record_list_destroy(pname); IGRAPH_FINALLY_CLEAN(1); } igraph_trie_destroy(&trie); @@ -280,7 +284,7 @@ igraph_error_t igraph_write_graph_lgl(const igraph_t *graph, FILE *outstream, names = NULL; } if (names) { - IGRAPH_CHECK(igraph_i_attribute_gettype(graph, &nametype, + IGRAPH_CHECK(igraph_i_attribute_get_type(graph, &nametype, IGRAPH_ATTRIBUTE_VERTEX, names)); if (nametype != IGRAPH_ATTRIBUTE_STRING) { IGRAPH_WARNINGF("Ignoring names attribute '%s', unknown attribute type.", names); @@ -294,7 +298,7 @@ igraph_error_t igraph_write_graph_lgl(const igraph_t *graph, FILE *outstream, weights = NULL; } if (weights) { - IGRAPH_CHECK(igraph_i_attribute_gettype(graph, &weighttype, + IGRAPH_CHECK(igraph_i_attribute_get_type(graph, &weighttype, IGRAPH_ATTRIBUTE_EDGE, weights)); if (weighttype != IGRAPH_ATTRIBUTE_NUMERIC) { IGRAPH_WARNINGF("Ignoring weights attribute '%s', unknown attribute type.", weights); diff --git a/src/vendor/cigraph/src/io/ncol-parser.y b/src/vendor/cigraph/src/io/ncol-parser.y index caec463cc29..e5bff3be2ec 100644 --- a/src/vendor/cigraph/src/io/ncol-parser.y +++ b/src/vendor/cigraph/src/io/ncol-parser.y @@ -95,7 +95,7 @@ input : /* empty */ ; edge : endpoints NEWLINE { - IGRAPH_YY_CHECK(igraph_vector_push_back(context->weights, 0.0)); + IGRAPH_YY_CHECK(igraph_vector_push_back(context->weights, 1.0)); } | endpoints weight NEWLINE { IGRAPH_YY_CHECK(igraph_vector_push_back(context->weights, $2)); diff --git a/src/vendor/cigraph/src/io/ncol.c b/src/vendor/cigraph/src/io/ncol.c index 8a06461b24f..f9ee490d196 100644 --- a/src/vendor/cigraph/src/io/ncol.c +++ b/src/vendor/cigraph/src/io/ncol.c @@ -81,10 +81,11 @@ void igraph_ncol_yylex_destroy_wrapper (void *scanner ) { * graph as an edge attribute called \quote weight\endquote. * \c IGRAPH_ADD_WEIGHTS_YES adds the weights (even if they * are not present in the file, in this case they are assumed - * to be zero). \c IGRAPH_ADD_WEIGHTS_NO does not add any + * to be 1). \c IGRAPH_ADD_WEIGHTS_NO does not add any * edge attribute. \c IGRAPH_ADD_WEIGHTS_IF_PRESENT adds the * attribute if and only if there is at least one explicit - * edge weight in the input file. + * edge weight in the input file, and edges without an explicit + * weight are assumed to have a weight of 1. * \param directed Whether to create a directed graph. As this format * was originally used only for undirected graphs there is no * information in the file about the directedness of the graph. @@ -114,9 +115,9 @@ igraph_error_t igraph_read_graph_ncol(igraph_t *graph, FILE *instream, igraph_trie_t trie = IGRAPH_TRIE_NULL; igraph_integer_t no_of_nodes; igraph_integer_t no_predefined = 0; - igraph_vector_ptr_t name, weight; - igraph_vector_ptr_t *pname = NULL, *pweight = NULL; - igraph_attribute_record_t namerec, weightrec; + igraph_attribute_record_list_t name, weight; + igraph_attribute_record_list_t *pname = NULL, *pweight = NULL; + igraph_attribute_record_t *namerec, *weightrec; const char *namestr = "name", *weightstr = "weight"; igraph_i_ncol_parsedata_t context; @@ -185,28 +186,32 @@ igraph_error_t igraph_read_graph_ncol(igraph_t *graph, FILE *instream, IGRAPH_WARNING("Unknown vertex/vertices found in NCOL file, predefined names extended."); } - /* Prepare attributes, if needed */ - + /* Prepare attributes if needed */ if (names) { - IGRAPH_CHECK(igraph_vector_ptr_init(&name, 1)); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &name); + IGRAPH_CHECK(igraph_attribute_record_list_init(&name, 1)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &name); + + namerec = igraph_attribute_record_list_get_ptr(&name, 0); + IGRAPH_CHECK(igraph_attribute_record_set_name(namerec, namestr)); + IGRAPH_CHECK(igraph_attribute_record_set_type(namerec, IGRAPH_ATTRIBUTE_STRING)); + IGRAPH_CHECK(igraph_strvector_update( + namerec->value.as_strvector, igraph_i_trie_borrow_keys(context.trie)) + ); + pname = &name; - namerec.name = namestr; - namerec.type = IGRAPH_ATTRIBUTE_STRING; - namerec.value = igraph_i_trie_borrow_keys(&trie); - VECTOR(name)[0] = &namerec; } if (weights == IGRAPH_ADD_WEIGHTS_YES || (weights == IGRAPH_ADD_WEIGHTS_IF_PRESENT && context.has_weights)) { + IGRAPH_CHECK(igraph_attribute_record_list_init(&weight, 1)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &weight); + + weightrec = igraph_attribute_record_list_get_ptr(&weight, 0); + IGRAPH_CHECK(igraph_attribute_record_set_name(weightrec, weightstr)); + IGRAPH_CHECK(igraph_attribute_record_set_type(weightrec, IGRAPH_ATTRIBUTE_NUMERIC)); + igraph_vector_swap(weightrec->value.as_vector, context.weights); - IGRAPH_CHECK(igraph_vector_ptr_init(&weight, 1)); - IGRAPH_FINALLY(igraph_vector_ptr_destroy, &weight); pweight = &weight; - weightrec.name = weightstr; - weightrec.type = IGRAPH_ATTRIBUTE_NUMERIC; - weightrec.value = &ws; - VECTOR(weight)[0] = &weightrec; } if (igraph_vector_int_empty(&edges)) { @@ -222,11 +227,11 @@ igraph_error_t igraph_read_graph_ncol(igraph_t *graph, FILE *instream, IGRAPH_CHECK(igraph_add_edges(graph, &edges, pweight)); if (pname) { - igraph_vector_ptr_destroy(pname); + igraph_attribute_record_list_destroy(pname); IGRAPH_FINALLY_CLEAN(1); } if (pweight) { - igraph_vector_ptr_destroy(pweight); + igraph_attribute_record_list_destroy(pweight); IGRAPH_FINALLY_CLEAN(1); } igraph_vector_destroy(&ws); @@ -309,7 +314,7 @@ igraph_error_t igraph_write_graph_ncol(const igraph_t *graph, FILE *outstream, names = NULL; } if (names) { - IGRAPH_CHECK(igraph_i_attribute_gettype(graph, &nametype, + IGRAPH_CHECK(igraph_i_attribute_get_type(graph, &nametype, IGRAPH_ATTRIBUTE_VERTEX, names)); if (nametype != IGRAPH_ATTRIBUTE_STRING) { IGRAPH_WARNINGF("Ignoring names attribute '%s', " @@ -324,7 +329,7 @@ igraph_error_t igraph_write_graph_ncol(const igraph_t *graph, FILE *outstream, weights = NULL; } if (weights) { - IGRAPH_CHECK(igraph_i_attribute_gettype(graph, &weighttype, + IGRAPH_CHECK(igraph_i_attribute_get_type(graph, &weighttype, IGRAPH_ATTRIBUTE_EDGE, weights)); if (weighttype != IGRAPH_ATTRIBUTE_NUMERIC) { IGRAPH_WARNINGF("Ignoring weights attribute '%s', " diff --git a/src/vendor/cigraph/src/io/pajek-header.h b/src/vendor/cigraph/src/io/pajek-header.h index caa2360e8f1..4500f8d7153 100644 --- a/src/vendor/cigraph/src/io/pajek-header.h +++ b/src/vendor/cigraph/src/io/pajek-header.h @@ -20,6 +20,7 @@ */ +#include "igraph_attributes.h" #include "igraph_error.h" #include "igraph_vector.h" #include "igraph_vector_ptr.h" @@ -53,9 +54,9 @@ typedef struct { igraph_integer_t actfrom; igraph_integer_t actto; igraph_trie_t *vertex_attribute_names; - igraph_vector_ptr_t *vertex_attributes; + igraph_attribute_record_list_t *vertex_attributes; igraph_trie_t *edge_attribute_names; - igraph_vector_ptr_t *edge_attributes; + igraph_attribute_record_list_t *edge_attributes; igraph_integer_t vertexid; igraph_integer_t actvertex; igraph_integer_t actedge; diff --git a/src/vendor/cigraph/src/io/pajek-parser.y b/src/vendor/cigraph/src/io/pajek-parser.y index 20d9a59ecfe..f70c640d55e 100644 --- a/src/vendor/cigraph/src/io/pajek-parser.y +++ b/src/vendor/cigraph/src/io/pajek-parser.y @@ -78,15 +78,17 @@ static igraph_error_t add_numeric_edge_attribute(const char *name, igraph_real_t value, igraph_i_pajek_parsedata_t *context); static igraph_error_t add_numeric_attribute(igraph_trie_t *names, - igraph_vector_ptr_t *attrs, + igraph_attribute_record_list_t *attrs, igraph_integer_t count, const char *attrname, + igraph_real_t default_value, igraph_integer_t vid, igraph_real_t number); static igraph_error_t add_string_attribute(igraph_trie_t *names, - igraph_vector_ptr_t *attrs, + igraph_attribute_record_list_t *attrs, igraph_integer_t count, const char *attrname, + const char *default_value, igraph_integer_t vid, const char *str, igraph_integer_t str_len); @@ -98,6 +100,10 @@ static igraph_error_t make_dynstr(const char *src, size_t len, char **res); static igraph_bool_t is_standard_vattr(const char *attrname); static igraph_bool_t is_standard_eattr(const char *attrname); static igraph_error_t deconflict_attrname(char **attrname); +static igraph_real_t get_default_value_for_numeric_vattr(const char *attrname); +static igraph_real_t get_default_value_for_numeric_eattr(const char *attrname); +static const char* get_default_value_for_string_vattr(const char *attrname); +static const char* get_default_value_for_string_eattr(const char *attrname); #define scanner context->scanner @@ -248,7 +254,6 @@ vertex: integer { }; vertexid: word { - IGRAPH_YY_CHECK(add_string_vertex_attribute("id", $1.str, $1.len, context)); IGRAPH_YY_CHECK(add_string_vertex_attribute("name", $1.str, $1.len, context)); }; @@ -548,49 +553,38 @@ int igraph_pajek_yyerror(YYLTYPE* locp, /* TODO: NA's */ static igraph_error_t add_numeric_attribute(igraph_trie_t *names, - igraph_vector_ptr_t *attrs, + igraph_attribute_record_list_t *attrs, igraph_integer_t count, const char *attrname, + igraph_real_t default_value, igraph_integer_t elem_id, igraph_real_t number) { igraph_integer_t attrsize = igraph_trie_size(names); igraph_integer_t id; igraph_vector_t *na; - igraph_attribute_record_t *rec; + igraph_attribute_record_t *prec; IGRAPH_CHECK(igraph_trie_get(names, attrname, &id)); if (id == attrsize) { - /* add a new attribute */ - rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - CHECK_OOM_RP(rec); - IGRAPH_FINALLY(igraph_free, rec); - - na = IGRAPH_CALLOC(1, igraph_vector_t); - CHECK_OOM_RP(na); - IGRAPH_FINALLY(igraph_free, na); - IGRAPH_VECTOR_INIT_FINALLY(na, count); + igraph_attribute_record_t rec; - rec->name = strdup(attrname); - CHECK_OOM_RP(rec->name); - IGRAPH_FINALLY(igraph_free, (void *) rec->name); + /* add a new attribute */ + IGRAPH_CHECK(igraph_attribute_record_init(&rec, attrname, IGRAPH_ATTRIBUTE_NUMERIC)); + IGRAPH_FINALLY(igraph_attribute_record_destroy, &rec); - rec->type = IGRAPH_ATTRIBUTE_NUMERIC; - rec->value = na; + IGRAPH_CHECK(igraph_attribute_record_set_default_numeric(&rec, default_value)); - IGRAPH_CHECK(igraph_vector_ptr_push_back(attrs, rec)); - IGRAPH_FINALLY_CLEAN(4); /* ownership of rec transferred to attrs */ + IGRAPH_CHECK(igraph_attribute_record_resize(&rec, count)); + IGRAPH_CHECK(igraph_attribute_record_list_push_back(attrs, &rec)); + IGRAPH_FINALLY_CLEAN(1); /* ownership of rec transferred to attrs */ } - rec = VECTOR(*attrs)[id]; - na = (igraph_vector_t *) rec->value; + prec = igraph_attribute_record_list_get_ptr(attrs, id); + na = prec->value.as_vector; if (igraph_vector_size(na) == elem_id) { IGRAPH_CHECK(igraph_vector_push_back(na, number)); } else if (igraph_vector_size(na) < elem_id) { - igraph_integer_t origsize=igraph_vector_size(na); - IGRAPH_CHECK(igraph_vector_resize(na, elem_id+1)); - for (;origsizename = strdup(attrname); - CHECK_OOM_RP(rec->name); - IGRAPH_FINALLY(igraph_free, (char *) rec->name); + IGRAPH_CHECK(igraph_attribute_record_init(&rec, attrname, IGRAPH_ATTRIBUTE_STRING)); + IGRAPH_FINALLY(igraph_attribute_record_destroy, &rec); - rec->type = IGRAPH_ATTRIBUTE_STRING; - rec->value = na; + IGRAPH_CHECK(igraph_attribute_record_set_default_string(&rec, default_value)); - IGRAPH_CHECK(igraph_vector_ptr_push_back(attrs, rec)); - IGRAPH_FINALLY_CLEAN(4); /* ownership of rec transferred to attrs */ + IGRAPH_CHECK(igraph_attribute_record_resize(&rec, count)); + IGRAPH_CHECK(igraph_attribute_record_list_push_back(attrs, &rec)); + IGRAPH_FINALLY_CLEAN(1); /* ownership of rec transferred to attrs */ } - rec = VECTOR(*attrs)[id]; - na = (igraph_strvector_t *) rec->value; + prec = igraph_attribute_record_list_get_ptr(attrs, id); + na = prec->value.as_strvector; if (igraph_strvector_size(na) <= elem_id) { IGRAPH_CHECK(igraph_strvector_resize(na, elem_id+1)); } @@ -675,7 +658,9 @@ static igraph_error_t add_string_vertex_attribute(const char *name, return add_string_attribute(context->vertex_attribute_names, context->vertex_attributes, context->vcount, - name, context->actvertex-1, + name, + get_default_value_for_string_vattr(name), + context->actvertex-1, value, len); } @@ -687,7 +672,9 @@ static igraph_error_t add_string_edge_attribute(const char *name, return add_string_attribute(context->edge_attribute_names, context->edge_attributes, context->actedge, - name, context->actedge-1, + name, + get_default_value_for_string_eattr(name), + context->actedge-1, value, len); } @@ -698,7 +685,9 @@ static igraph_error_t add_numeric_vertex_attribute(const char *name, return add_numeric_attribute(context->vertex_attribute_names, context->vertex_attributes, context->vcount, - name, context->actvertex-1, + name, + get_default_value_for_numeric_vattr(name), + context->actvertex-1, value); } @@ -709,7 +698,9 @@ static igraph_error_t add_numeric_edge_attribute(const char *name, return add_numeric_attribute(context->edge_attribute_names, context->edge_attributes, context->actedge, - name, context->actedge-1, + name, + get_default_value_for_numeric_eattr(name), + context->actedge-1, value); } @@ -717,10 +708,10 @@ static igraph_error_t add_bipartite_type(igraph_i_pajek_parsedata_t *context) { const char *attrname="type"; igraph_trie_t *names=context->vertex_attribute_names; - igraph_vector_ptr_t *attrs=context->vertex_attributes; + igraph_attribute_record_list_t *attrs=context->vertex_attributes; igraph_integer_t n=context->vcount, n1=context->vcount2; igraph_integer_t attrid, attrsize = igraph_trie_size(names); - igraph_attribute_record_t *rec; + igraph_attribute_record_t* rec; igraph_vector_bool_t *na; if (n1 > n) { @@ -735,29 +726,13 @@ static igraph_error_t add_bipartite_type(igraph_i_pajek_parsedata_t *context) { IGRAPH_ASSERT(attrid == attrsize); /* add a new attribute */ - rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - CHECK_OOM_RP(rec); - IGRAPH_FINALLY(igraph_free, rec); - - na = IGRAPH_CALLOC(1, igraph_vector_bool_t); - CHECK_OOM_RP(na); - IGRAPH_FINALLY(igraph_free, na); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(na, n); - - rec->name = strdup(attrname); - CHECK_OOM_RP(rec->name); - IGRAPH_FINALLY(igraph_free, (char *) rec->name); + IGRAPH_CHECK(igraph_attribute_record_list_push_back_new(attrs, &rec)); + IGRAPH_CHECK(igraph_attribute_record_set_name(rec, attrname)); + IGRAPH_CHECK(igraph_attribute_record_set_type(rec, IGRAPH_ATTRIBUTE_BOOLEAN)); + IGRAPH_CHECK(igraph_attribute_record_resize(rec, n)); - rec->type = IGRAPH_ATTRIBUTE_BOOLEAN; - rec->value = na; - - IGRAPH_CHECK(igraph_vector_ptr_push_back(attrs, rec)); - IGRAPH_FINALLY_CLEAN(4); /* ownership of 'rec' transferred to 'attrs' */ - - for (igraph_integer_t i=0; ivalue.as_vector_bool; + for (igraph_integer_t i = n1; i < n; i++) { VECTOR(*na)[i] = true; } @@ -797,7 +772,7 @@ static igraph_bool_t is_standard_vattr(const char *attrname) { "font", "url", "color", "framecolor", "labelcolor" }; - for (size_t i=0; i < sizeof(names) / sizeof(names[0]); i++) { + for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); i++) { if (strcmp(attrname, names[i]) == 0) { return true; } @@ -839,3 +814,108 @@ static igraph_error_t deconflict_attrname(char **attrname) { *attrname = tmp; return IGRAPH_SUCCESS; } + +typedef struct { + const char* name; + igraph_real_t default_value; +} attribute_numeric_defaults_t; + +typedef struct { + const char* name; + const char* default_value; +} attribute_string_defaults_t; + +/* The defaults listed below are Pajek's built-in defaults unless the user + * overrides them. + * + * See: https://nascol.discourse.group/t/pajek-file-format-default-values-for-attributes/38/2 + */ + +const attribute_numeric_defaults_t vattr_numeric_defaults[] = { + { "xfact", 1 }, + { "yfact", 1 }, + { "labeldist", 20 }, + { "labeldegree2", 285 }, + { "framewidth", 1 }, + { "fontsize", 15 }, + { "rotation", 0 }, + { "radius", 0 }, + { "diamondratio", 0.01 }, + { "labeldegree", 0 }, + { 0 } +}; + +const attribute_string_defaults_t vattr_string_defaults[] = { + { "color", "LightOrange" }, + { "framecolor", "Brown" }, + { "labelcolor", "Maroon" }, + { 0 } +}; + +const attribute_numeric_defaults_t eattr_numeric_defaults[] = { + { "arrowsize", 1 }, + { "edgewidth", 2 }, + { "hook1", 0 }, + { "hook2", 0 }, + { "angle1", 0 }, + { "angle2", 0 }, + { "velocity1", 1 }, + { "velocity2", 1 }, + { "arrowpos", 0 }, + { "labelpos", 0.5 }, + { "labelangle", 10 }, + { "labelangle2", 90 }, + { "labeldegree", 0 }, + { "fontsize", 15 }, + { 0 } +}; + +const attribute_string_defaults_t eattr_string_defaults[] = { + { "color", "MidnightBlue" }, + { "labelcolor", "Black" }, + { 0 } +}; + +static igraph_real_t get_default_value_for_numeric_attr( + const char *attrname, const attribute_numeric_defaults_t* table +) { + const attribute_numeric_defaults_t* ptr; + + for (ptr = table; ptr->name != 0; ptr++) { + if (!strcmp(attrname, ptr->name)) { + return ptr->default_value; + } + } + + return IGRAPH_NAN; +} + +static const char* get_default_value_for_string_attr( + const char *attrname, const attribute_string_defaults_t* table +) { + const attribute_string_defaults_t* ptr; + + for (ptr = table; ptr->name != 0; ptr++) { + if (!strcmp(attrname, ptr->name)) { + return ptr->default_value; + } + } + + return ""; +} + +static igraph_real_t get_default_value_for_numeric_vattr(const char *attrname) { + return get_default_value_for_numeric_attr(attrname, vattr_numeric_defaults); +} + +static igraph_real_t get_default_value_for_numeric_eattr(const char *attrname) { + return get_default_value_for_numeric_attr(attrname, eattr_numeric_defaults); +} + +static const char* get_default_value_for_string_vattr(const char *attrname) { + return get_default_value_for_string_attr(attrname, vattr_string_defaults); +} + +static const char* get_default_value_for_string_eattr(const char *attrname) { + return get_default_value_for_string_attr(attrname, eattr_string_defaults); +} diff --git a/src/vendor/cigraph/src/io/pajek.c b/src/vendor/cigraph/src/io/pajek.c index d54c293bb87..ea2f524858c 100644 --- a/src/vendor/cigraph/src/io/pajek.c +++ b/src/vendor/cigraph/src/io/pajek.c @@ -26,11 +26,10 @@ #include "igraph_error.h" #include "igraph_interface.h" #include "igraph_memory.h" +#include "igraph_misc.h" /* IGRAPH_STATIC_ASSERT */ #include "graph/attributes.h" -#include "internal/hacks.h" /* IGRAPH_STATIC_ASSERT */ - #include "io/pajek-header.h" #include "io/parsers/pajek-parser.h" @@ -48,32 +47,6 @@ void igraph_pajek_yylex_destroy_wrapper (void *scanner ) { (void) igraph_pajek_yylex_destroy(scanner); } -void igraph_i_pajek_destroy_attr_vector(igraph_vector_ptr_t *attrs) { - const igraph_integer_t attr_count = igraph_vector_ptr_size(attrs); - for (igraph_integer_t i = 0; i < attr_count; i++) { - igraph_attribute_record_t *rec = VECTOR(*attrs)[i]; - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *vec = (igraph_vector_t*) rec->value; - igraph_vector_destroy(vec); - IGRAPH_FREE(vec); - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - igraph_vector_bool_t *vec = (igraph_vector_bool_t*) rec->value; - igraph_vector_bool_destroy(vec); - IGRAPH_FREE(vec); - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *strvec = (igraph_strvector_t *)rec->value; - igraph_strvector_destroy(strvec); - IGRAPH_FREE(strvec); - } else { - /* Must never reach here */ - IGRAPH_FATAL("Unknown attribute type encountered."); - } - IGRAPH_FREE(rec->name); - IGRAPH_FREE(rec); - } - igraph_vector_ptr_destroy(attrs); -} - /** * \function igraph_read_graph_pajek * \brief Reads a file in Pajek format. @@ -135,11 +108,10 @@ void igraph_i_pajek_destroy_attr_vector(igraph_vector_ptr_t *attrs) { * character is appended to it to avoid conflict. * * - * In addition the following vertex attributes might be added: \c id - * and \c name are added (with the same value) if there are vertex IDs in the - * file. \c id is deprecated in favour of \c name and will no longer be used - * by future versions of igraph. \c x and \c y, and potentially \c z are also - * added if there are vertex coordinates in the file. + * In addition the following vertex attributes might be added: \c name is added + * (with the same value) if there are vertex IDs in the file. + * \c x and \c y, and potentially \c z are also added if there are vertex + * coordinates in the file. * * * The \c weight edge attribute will be added if there are edge weights present. @@ -172,21 +144,21 @@ igraph_error_t igraph_read_graph_pajek(igraph_t *graph, FILE *instream) { igraph_vector_int_t edges; igraph_trie_t vattrnames; - igraph_vector_ptr_t vattrs; + igraph_attribute_record_list_t vattrs; igraph_trie_t eattrnames; - igraph_vector_ptr_t eattrs; - igraph_integer_t i, j; + igraph_attribute_record_list_t eattrs; + igraph_integer_t i; igraph_i_pajek_parsedata_t context; IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); IGRAPH_TRIE_INIT_FINALLY(&vattrnames, 1); - IGRAPH_CHECK(igraph_vector_ptr_init(&vattrs, 0)); - IGRAPH_FINALLY(igraph_i_pajek_destroy_attr_vector, &vattrs); + IGRAPH_CHECK(igraph_attribute_record_list_init(&vattrs, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &vattrs); IGRAPH_TRIE_INIT_FINALLY(&eattrnames, 1); - IGRAPH_CHECK(igraph_vector_ptr_init(&eattrs, 0)); - IGRAPH_FINALLY(igraph_i_pajek_destroy_attr_vector, &eattrs); + IGRAPH_CHECK(igraph_attribute_record_list_init(&eattrs, 0)); + IGRAPH_FINALLY(igraph_attribute_record_list_destroy, &eattrs); context.directed = false; /* assume undirected until an element implying directedness is encountered */ context.vector = &edges; @@ -235,33 +207,10 @@ igraph_error_t igraph_read_graph_pajek(igraph_t *graph, FILE *instream) { } /* Prepare attributes */ - const igraph_integer_t eattr_count = igraph_vector_ptr_size(&eattrs); + const igraph_integer_t eattr_count = igraph_attribute_record_list_size(&eattrs); for (i = 0; i < eattr_count; i++) { - igraph_attribute_record_t *rec = VECTOR(eattrs)[i]; - if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) { - igraph_vector_t *vec = (igraph_vector_t*)rec->value; - igraph_integer_t origsize = igraph_vector_size(vec); - IGRAPH_CHECK(igraph_vector_resize(vec, context.actedge)); - for (j = origsize; j < context.actedge; j++) { - VECTOR(*vec)[j] = IGRAPH_NAN; - } - } else if (rec->type == IGRAPH_ATTRIBUTE_BOOLEAN) { - /* Boolean attributes are not currently added by the parser. - * This section is here for future-proofing. */ - igraph_vector_bool_t *vec = (igraph_vector_bool_t*)rec->value; - igraph_integer_t origsize = igraph_vector_bool_size(vec); - IGRAPH_CHECK(igraph_vector_bool_resize(vec, context.actedge)); - for (j = origsize; j < context.actedge; j++) { - VECTOR(*vec)[j] = 0; - } - } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) { - igraph_strvector_t *strvec = (igraph_strvector_t*)rec->value; - /* strvector_resize() adds empty strings */ - IGRAPH_CHECK(igraph_strvector_resize(strvec, context.actedge)); - } else { - /* Must never reach here */ - IGRAPH_FATAL("Unknown attribute type encountered."); - } + igraph_attribute_record_t *rec = igraph_attribute_record_list_get_ptr(&eattrs, i); + IGRAPH_CHECK(igraph_attribute_record_resize(rec, context.actedge)); } /* Create graph */ @@ -271,9 +220,9 @@ igraph_error_t igraph_read_graph_pajek(igraph_t *graph, FILE *instream) { IGRAPH_CHECK(igraph_add_edges(graph, &edges, &eattrs)); igraph_vector_int_destroy(&edges); - igraph_i_pajek_destroy_attr_vector(&eattrs); + igraph_attribute_record_list_destroy(&eattrs); igraph_trie_destroy(&eattrnames); - igraph_i_pajek_destroy_attr_vector(&vattrs); + igraph_attribute_record_list_destroy(&vattrs); igraph_trie_destroy(&vattrnames); igraph_pajek_yylex_destroy(context.scanner); IGRAPH_FINALLY_CLEAN(7); /* +1 for 'graph' */ @@ -445,7 +394,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) igraph_bool_t write_vertex_attrs = false; /* Same order as the #define's */ - const char *vnames[] = { "id", "x", "y", "z", "shape", "xfact", "yfact", + const char *vnames[] = { "name", "x", "y", "z", "shape", "xfact", "yfact", "labeldist", "labeldegree2", "framewidth", "fontsize", "rotation", "radius", "diamondratio", "labeldegree", @@ -527,7 +476,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) /* Check if graph is bipartite, i.e. whether it has a Boolean 'type' vertex attribute. */ if (igraph_i_attribute_has_attr(graph, IGRAPH_ATTRIBUTE_VERTEX, "type")) { igraph_attribute_type_t type_type; - IGRAPH_CHECK(igraph_i_attribute_gettype(graph, &type_type, IGRAPH_ATTRIBUTE_VERTEX, "type")); + IGRAPH_CHECK(igraph_i_attribute_get_type(graph, &type_type, IGRAPH_ATTRIBUTE_VERTEX, "type")); if (type_type == IGRAPH_ATTRIBUTE_BOOLEAN) { bipartite = true; write_vertex_attrs = true; /* Count top and bottom vertices, we go over them twice, @@ -578,7 +527,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) memset(vtypes, 0, sizeof(vtypes[0])*V_LAST); for (igraph_integer_t i = 0; i < V_LAST; i++) { if (igraph_i_attribute_has_attr(graph, IGRAPH_ATTRIBUTE_VERTEX, vnames[i])) { - IGRAPH_CHECK(igraph_i_attribute_gettype( + IGRAPH_CHECK(igraph_i_attribute_get_type( graph, &vtypes[i], IGRAPH_ATTRIBUTE_VERTEX, vnames[i])); write_vertex_attrs = true; } else { @@ -588,7 +537,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) for (igraph_integer_t i = 0; i < (igraph_integer_t) (sizeof(vnumnames) / sizeof(vnumnames[0])); i++) { igraph_attribute_type_t type; if (igraph_i_attribute_has_attr(graph, IGRAPH_ATTRIBUTE_VERTEX, vnumnames[i])) { - IGRAPH_CHECK(igraph_i_attribute_gettype( + IGRAPH_CHECK(igraph_i_attribute_get_type( graph, &type, IGRAPH_ATTRIBUTE_VERTEX, vnumnames[i])); if (type == IGRAPH_ATTRIBUTE_NUMERIC) { IGRAPH_CHECK(igraph_vector_int_push_back(&vx_numa, i)); @@ -598,7 +547,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) for (igraph_integer_t i = 0; i < (igraph_integer_t) (sizeof(vstrnames) / sizeof(vstrnames[0])); i++) { igraph_attribute_type_t type; if (igraph_i_attribute_has_attr(graph, IGRAPH_ATTRIBUTE_VERTEX, vstrnames[i])) { - IGRAPH_CHECK(igraph_i_attribute_gettype( + IGRAPH_CHECK(igraph_i_attribute_get_type( graph, &type, IGRAPH_ATTRIBUTE_VERTEX, vstrnames[i])); if (type == IGRAPH_ATTRIBUTE_STRING) { IGRAPH_CHECK(igraph_vector_int_push_back(&vx_stra, i)); @@ -700,7 +649,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) /* TODO: refactor and simplify since only "weight" is relevant */ for (igraph_integer_t i = 0; i < E_LAST; i++) { if (igraph_i_attribute_has_attr(graph, IGRAPH_ATTRIBUTE_EDGE, enames[i])) { - IGRAPH_CHECK(igraph_i_attribute_gettype( + IGRAPH_CHECK(igraph_i_attribute_get_type( graph, &etypes[i], IGRAPH_ATTRIBUTE_EDGE, enames[i])); } else { etypes[i] = (igraph_attribute_type_t) -1; @@ -709,7 +658,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) for (igraph_integer_t i = 0; i < (igraph_integer_t) (sizeof(enumnames) / sizeof(enumnames[0])); i++) { igraph_attribute_type_t type; if (igraph_i_attribute_has_attr(graph, IGRAPH_ATTRIBUTE_EDGE, enumnames[i])) { - IGRAPH_CHECK(igraph_i_attribute_gettype( + IGRAPH_CHECK(igraph_i_attribute_get_type( graph, &type, IGRAPH_ATTRIBUTE_EDGE, enumnames[i])); if (type == IGRAPH_ATTRIBUTE_NUMERIC) { IGRAPH_CHECK(igraph_vector_int_push_back(&ex_numa, i)); @@ -719,7 +668,7 @@ igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream) for (igraph_integer_t i = 0; i < (igraph_integer_t) (sizeof(estrnames) / sizeof(estrnames[0])); i++) { igraph_attribute_type_t type; if (igraph_i_attribute_has_attr(graph, IGRAPH_ATTRIBUTE_EDGE, estrnames[i])) { - IGRAPH_CHECK(igraph_i_attribute_gettype( + IGRAPH_CHECK(igraph_i_attribute_get_type( graph, &type, IGRAPH_ATTRIBUTE_EDGE, estrnames[i])); if (type == IGRAPH_ATTRIBUTE_STRING) { IGRAPH_CHECK(igraph_vector_int_push_back(&ex_stra, i)); diff --git a/src/vendor/cigraph/src/isomorphism/bliss.cc b/src/vendor/cigraph/src/isomorphism/bliss.cc index fedc3c3c421..3a90a052cb8 100644 --- a/src/vendor/cigraph/src/isomorphism/bliss.cc +++ b/src/vendor/cigraph/src/isomorphism/bliss.cc @@ -29,6 +29,7 @@ #include "core/exceptions.h" #include +#include #include using namespace bliss; @@ -191,7 +192,7 @@ struct AbortChecker { AbortChecker() : aborted(false) { } bool operator()() { - if (igraph_allow_interruption(NULL) != IGRAPH_SUCCESS) { + if (igraph_allow_interruption() != IGRAPH_SUCCESS) { aborted = true; return true; } @@ -231,6 +232,43 @@ class AutCollector { /** * \function igraph_canonical_permutation + * \brief Canonical permutation of a graph. + * + * This function computes the vertex permutation which transforms + * the graph into a canonical form. Two graphs have the same canonical form if + * and only if they are isomorphic. Use \ref igraph_is_same_graph() to compare + * two canonical forms. + * + * + * The current implementation uses the BLISS isomorphism algorithms with + * sensible defaults. Use \ref igaph_canonical_permutation_bliss() to fine-tune + * the parameters. + * + * \param graph The input graph. Multiple edges between the same nodes + * are not supported and will cause an incorrect result to be returned. + * \param colors An optional vertex color vector for the graph. Supply a + * null pointer is the graph is not colored. + * \param labeling Pointer to a vector, the result is stored here. The + * permutation takes vertex 0 to the first element of the vector, + * vertex 1 to the second, etc. The vector will be resized as + * needed. + * \return Error code. + * + * \sa \ref igraph_is_same_graph() + * + * Time complexity: exponential, in practice it is fast for many graphs. + */ +igraph_error_t igraph_canonical_permutation( + const igraph_t *graph, const igraph_vector_int_t *colors, + igraph_vector_int_t *labeling +) { + return igraph_canonical_permutation_bliss( + graph, colors, labeling, IGRAPH_BLISS_FL, NULL + ); +} + +/** + * \function igraph_canonical_permutation_bliss * \brief Canonical permutation using Bliss. * * This function computes the vertex permutation which transforms @@ -258,8 +296,11 @@ class AutCollector { * * Time complexity: exponential, in practice it is fast for many graphs. */ -igraph_error_t igraph_canonical_permutation(const igraph_t *graph, const igraph_vector_int_t *colors, - igraph_vector_int_t *labeling, igraph_bliss_sh_t sh, igraph_bliss_info_t *info) { +igraph_error_t igraph_canonical_permutation_bliss( + const igraph_t *graph, const igraph_vector_int_t *colors, + igraph_vector_int_t *labeling, igraph_bliss_sh_t sh, + igraph_bliss_info_t *info +) { IGRAPH_HANDLE_EXCEPTIONS( AbstractGraph *g = bliss_from_igraph(graph); IGRAPH_FINALLY(bliss_free_graph, g); @@ -290,18 +331,53 @@ igraph_error_t igraph_canonical_permutation(const igraph_t *graph, const igraph_ } /** - * \function igraph_automorphisms - * \brief Number of automorphisms using Bliss (deprecated alias). + * \function igraph_count_automorphisms + * \brief Number of automorphisms of a graph. + * + * This function computes the number of automorphisms of a graph. Since the + * number of automorphisms may be very large, the result is returned as an + * \c igraph_real_t instead of an integer. If the number of automorphisms + * is larger than what can be represented in an \c igraph_real_t and you need + * the exact number, use \ref igraph_count_automorphisms_bliss(), which can + * return the number as a string. + * + * \param graph The input graph. Multiple edges between the same nodes + * are not supported and will cause an incorrect result to be returned. + * \param colors An optional vertex color vector for the graph. Supply a + * null pointer is the graph is not colored. + * \param result Pointer to an \c igraph_real_t, the number of automorphisms + * will be returned here. + * \return Error code. \c IGRAPH_EOVERFLOW if the number of automorphisms is + * too large to be represented in an \c igraph_real_t . * - * \deprecated-by igraph_count_automorphisms 0.10.5 + * Time complexity: exponential, in practice it is fast for many graphs. */ -igraph_error_t igraph_automorphisms(const igraph_t *graph, const igraph_vector_int_t *colors, - igraph_bliss_sh_t sh, igraph_bliss_info_t *info) { - return igraph_count_automorphisms(graph, colors, sh, info); +igraph_error_t igraph_count_automorphisms( + const igraph_t *graph, const igraph_vector_int_t *colors, + igraph_real_t *result +) { + igraph_bliss_info_t info; + double x; + + IGRAPH_CHECK(igraph_count_automorphisms_bliss(graph, colors, IGRAPH_BLISS_FL, &info)); + + x = strtod(info.group_size, NULL); + igraph_free(info.group_size); + + if (x == 0) { + return IGRAPH_FAILURE; + } else if (x == HUGE_VAL) { + return IGRAPH_EOVERFLOW; + } else { + if (result) { + *result = x; + } + return IGRAPH_SUCCESS; + } } /** - * \function igraph_count_automorphisms + * \function igraph_count_automorphisms_bliss * \brief Number of automorphisms using Bliss. * * The number of automorphisms of a graph is computed using Bliss. The @@ -322,8 +398,10 @@ igraph_error_t igraph_automorphisms(const igraph_t *graph, const igraph_vector_i * * Time complexity: exponential, in practice it is fast for many graphs. */ -igraph_error_t igraph_count_automorphisms(const igraph_t *graph, const igraph_vector_int_t *colors, - igraph_bliss_sh_t sh, igraph_bliss_info_t *info) { +igraph_error_t igraph_count_automorphisms_bliss( + const igraph_t *graph, const igraph_vector_int_t *colors, + igraph_bliss_sh_t sh, igraph_bliss_info_t *info +) { IGRAPH_HANDLE_EXCEPTIONS( AbstractGraph *g = bliss_from_igraph(graph); IGRAPH_FINALLY(bliss_free_graph, g); @@ -349,6 +427,39 @@ igraph_error_t igraph_count_automorphisms(const igraph_t *graph, const igraph_ve /** * \function igraph_automorphism_group + * \brief Automorphism group generators of a graph. + * + * This function computes the generators of the automorphism group of a graph. + * The generator set may not be minimal and may depend on the specific parameters + * of the algorithm under the hood. The generators are permutations represented + * using zero-based indexing. + * + * + * The current implementation uses BLISS behind the scenes and the result may + * be dependent on the splitting heuristics. Use \ref igraph_automorphism_group_bliss() + * if you want to fine-tune the splitting heuristics. + * + * \param graph The input graph. Multiple edges between the same nodes + * are not supported and will cause an incorrect result to be returned. + * \param colors An optional vertex color vector for the graph. Supply a + * null pointer is the graph is not colored. + * \param generators Must be an initialized interger vector list. + * The generators of the automorphism group will be stored here. + * \return Error code. + * + * Time complexity: exponential, in practice it is fast for many graphs. + */ +igraph_error_t igraph_automorphism_group( + const igraph_t *graph, const igraph_vector_int_t *colors, + igraph_vector_int_list_t *generators +) { + return igraph_automorphism_group_bliss( + graph, colors, generators, IGRAPH_BLISS_FL, NULL + ); +} + +/** + * \function igraph_automorphism_group_bliss * \brief Automorphism group generators using Bliss. * * The generators of the automorphism group of a graph are computed @@ -371,9 +482,11 @@ igraph_error_t igraph_count_automorphisms(const igraph_t *graph, const igraph_ve * * Time complexity: exponential, in practice it is fast for many graphs. */ -igraph_error_t igraph_automorphism_group( - const igraph_t *graph, const igraph_vector_int_t *colors, igraph_vector_int_list_t *generators, - igraph_bliss_sh_t sh, igraph_bliss_info_t *info) { +igraph_error_t igraph_automorphism_group_bliss( + const igraph_t *graph, const igraph_vector_int_t *colors, + igraph_vector_int_list_t *generators, igraph_bliss_sh_t sh, + igraph_bliss_info_t *info +) { IGRAPH_HANDLE_EXCEPTIONS( AbstractGraph *g = bliss_from_igraph(graph); IGRAPH_FINALLY(bliss_free_graph, g); @@ -431,7 +544,7 @@ igraph_error_t igraph_automorphism_group( * * * Isomorphism testing is implemented by producing the canonical form - * of both graphs using \ref igraph_canonical_permutation() and + * of both graphs using \ref igraph_canonical_permutation_bliss() and * comparing them. * * \param graph1 The first input graph. Multiple edges between the same nodes @@ -519,8 +632,8 @@ igraph_error_t igraph_isomorphic_bliss(const igraph_t *graph1, const igraph_t *g IGRAPH_VECTOR_INT_INIT_FINALLY(&perm1, no_of_nodes); IGRAPH_VECTOR_INT_INIT_FINALLY(&perm2, no_of_nodes); - IGRAPH_CHECK(igraph_canonical_permutation(graph1, colors1, &perm1, sh, info1)); - IGRAPH_CHECK(igraph_canonical_permutation(graph2, colors2, &perm2, sh, info2)); + IGRAPH_CHECK(igraph_canonical_permutation_bliss(graph1, colors1, &perm1, sh, info1)); + IGRAPH_CHECK(igraph_canonical_permutation_bliss(graph2, colors2, &perm2, sh, info2)); IGRAPH_CHECK(igraph_vector_int_resize(mymap12, no_of_nodes)); diff --git a/src/vendor/cigraph/src/isomorphism/vf2.c b/src/vendor/cigraph/src/isomorphism/vf2.c index 782141f0048..e230280706c 100644 --- a/src/vendor/cigraph/src/isomorphism/vf2.c +++ b/src/vendor/cigraph/src/isomorphism/vf2.c @@ -885,7 +885,7 @@ static igraph_error_t igraph_i_count_isomorphisms_vf2_cb( * \p edge_compat_fn. * \return Error code. * - * \sa igraph_count_automorphisms() + * \sa igraph_count_automorphisms_bliss() * * Time complexity: exponential. */ diff --git a/src/vendor/cigraph/src/linalg/eigen.c b/src/vendor/cigraph/src/linalg/eigen.c index 52ee6c711bd..c59bace9beb 100644 --- a/src/vendor/cigraph/src/linalg/eigen.c +++ b/src/vendor/cigraph/src/linalg/eigen.c @@ -1143,11 +1143,11 @@ static igraph_error_t igraph_i_eigen_checks(const igraph_matrix_t *A, if (A) { if (n != igraph_matrix_ncol(A) || n != igraph_matrix_nrow(A)) { - IGRAPH_ERROR("Invalid matrix", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Eigenvector calculations need a square matrix.", IGRAPH_EINVAL); } } else if (sA) { if (n != igraph_sparsemat_ncol(sA) || n != igraph_sparsemat_nrow(sA)) { - IGRAPH_ERROR("Invalid matrix", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Eigenvector calculations need a square matrix.", IGRAPH_EINVAL); } } diff --git a/src/vendor/cigraph/src/linalg/lapack.c b/src/vendor/cigraph/src/linalg/lapack.c index c50fe55cd56..6fdf4b3b74b 100644 --- a/src/vendor/cigraph/src/linalg/lapack.c +++ b/src/vendor/cigraph/src/linalg/lapack.c @@ -208,7 +208,7 @@ igraph_error_t igraph_lapack_dgetrs(igraph_bool_t transpose, const igraph_matrix ldb = n > 0 ? n : 1; if (n != igraph_matrix_ncol(a)) { - IGRAPH_ERROR("Cannot LU solve matrix.", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Cannot LU solve non-square matrix.", IGRAPH_EINVAL); } if (n != igraph_matrix_nrow(b)) { IGRAPH_ERROR("Cannot LU solve matrix, RHS of wrong size.", IGRAPH_EINVAL); @@ -320,7 +320,7 @@ igraph_error_t igraph_lapack_dgesv(igraph_matrix_t *a, igraph_vector_int_t *ipiv igraph_vector_fortran_int_t vipiv; if (n != igraph_matrix_ncol(a)) { - IGRAPH_ERROR("Cannot LU solve matrix.", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Cannot LU solve non-square matrix.", IGRAPH_EINVAL); } if (n != igraph_matrix_nrow(b)) { IGRAPH_ERROR("Cannot LU solve matrix, RHS of wrong size.", IGRAPH_EINVAL); @@ -459,7 +459,7 @@ igraph_error_t igraph_lapack_dsyevr(const igraph_matrix_t *A, int lwork = -1, liwork = -1; if (n != igraph_matrix_ncol(A)) { - IGRAPH_ERROR("Cannot find eigenvalues/vectors.", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Cannot find eigenvalues/vectors of non-square matrix.", IGRAPH_EINVAL); } if (which == IGRAPH_LAPACK_DSYEV_INTERVAL && (vestimate < 1 || vestimate > n)) { @@ -641,7 +641,7 @@ igraph_error_t igraph_lapack_dgeev(const igraph_matrix_t *A, int error = *info; if (igraph_matrix_ncol(A) != n) { - IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev).", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Cannot calculate eigenvalues of non-square matrix.", IGRAPH_EINVAL); } IGRAPH_CHECK(igraph_matrix_init_copy(&Acopy, A)); @@ -868,7 +868,7 @@ igraph_error_t igraph_lapack_dgeevx(igraph_lapack_dgeevx_balance_t balance, ihi = &ihi_dummy; } if (igraph_matrix_ncol(A) != n) { - IGRAPH_ERROR("Cannot calculate eigenvalues (dgeevx).", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Cannot calculate eigenvalues of non-square matrix.", IGRAPH_EINVAL); } switch (balance) { @@ -1003,7 +1003,7 @@ igraph_error_t igraph_lapack_dgehrd(const igraph_matrix_t *A, int i; if (igraph_matrix_ncol(A) != n) { - IGRAPH_ERROR("Hessenberg reduction failed.", IGRAPH_NONSQUARE); + IGRAPH_ERROR("Hessenberg reduction failed on non-square matrix.", IGRAPH_EINVAL); } if (ilo < 1 || ihi > n || ilo > ihi) { diff --git a/src/vendor/cigraph/src/misc/bipartite.c b/src/vendor/cigraph/src/misc/bipartite.c index 3e5da770ae2..3c36b4cf4c5 100644 --- a/src/vendor/cigraph/src/misc/bipartite.c +++ b/src/vendor/cigraph/src/misc/bipartite.c @@ -280,8 +280,7 @@ static igraph_error_t igraph_i_bipartite_projection(const igraph_t *graph, IGRAPH_FINALLY(igraph_destroy, proj); /* copy graph attributes */ - IGRAPH_I_ATTRIBUTE_DESTROY(proj); - IGRAPH_I_ATTRIBUTE_COPY(proj, graph, /* graph */ true, /* vertex */ false, /* edge */ false); + IGRAPH_CHECK(igraph_i_attribute_copy(proj, graph, true, /* vertex= */ false, /* edge= */ false)); /* copy vertex attributes */ IGRAPH_CHECK(igraph_i_attribute_permute_vertices(graph, proj, &vertex_perm)); @@ -558,7 +557,7 @@ igraph_error_t igraph_create_bipartite(igraph_t *graph, const igraph_vector_bool igraph_integer_t i; if (no_of_edges % 2 != 0) { - IGRAPH_ERROR("Invalid (odd) edges vector", IGRAPH_EINVEVECTOR); + IGRAPH_ERROR("Invalid (odd) edges vector", IGRAPH_EINVAL); } no_of_edges /= 2; @@ -1131,6 +1130,82 @@ igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t * return IGRAPH_SUCCESS; } +/** + * \function igraph_bipartite_game_gnm_multi + * \brief Generate a random bipartite graph with multi-edges. + * + * In the G(n1, n2, m) model we uniformly choose \p m edges to realize + * between the \p n1 bottom vertices and \p n2 top vertices. + * + * \param graph Pointer to an uninitialized igraph graph, the result + * is stored here. + * \param types Pointer to an initialized boolean vector, or a null + * pointer. If not a null pointer, then the vertex types are stored + * here. Bottom vertices come first, n1 of them, then n2 top + * vertices. + * \param n1 The number of bottom vertices. + * \param n2 The number of top vertices. + * \param m The number of edges. + * \param directed Boolean, whether to generate a directed graph. See + * also the \p mode argument. + * \param mode Specifies how to direct the edges in directed + * graphs. If it is \c IGRAPH_OUT, then directed edges point from + * bottom vertices to top vertices. If it is \c IGRAPH_IN, edges + * point from top vertices to bottom vertices. \c IGRAPH_OUT and + * \c IGRAPH_IN do not generate mutual edges. If this argument is + * \c IGRAPH_ALL, then each edge direction is considered + * independently and mutual edges might be generated. This + * argument is ignored for undirected graphs. + * \return Error code. + * + * \sa \ref igraph_erdos_renyi_game_gnm() for the unipartite version, + * \ref igraph_bipartite_game_gnp() for the G(n1, n2, p) model. + * + * Time complexity: O(|V|+|E|), linear in the number of vertices and + * edges. + */ + +static igraph_error_t igraph_i_bipartite_game_gnm_multi( + igraph_t *graph, igraph_vector_bool_t *types, + igraph_integer_t n1, igraph_integer_t n2, + igraph_integer_t m, igraph_bool_t directed, + igraph_neimode_t mode +) { + igraph_integer_t n; + igraph_vector_int_t edges; + + IGRAPH_SAFE_ADD(n1, n2, &n); + + IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, 0); + IGRAPH_CHECK(igraph_vector_int_reserve(&edges, m * 2)); + + RNG_BEGIN(); + for (igraph_integer_t i = 0; i < m; i++) { + igraph_integer_t to, from; + + to = RNG_INTEGER(n1, n - 1); + from = RNG_INTEGER(0, n1 - 1); + + /* flip unconditionally for IGRAPH_IN, or with probability 0.5 for + * IGRAPH_ALL */ + if (mode == IGRAPH_IN || (mode == IGRAPH_ALL && RNG_UNIF01() < 0.5)) { + igraph_vector_int_push_back(&edges, to); + igraph_vector_int_push_back(&edges, from); + } else { + igraph_vector_int_push_back(&edges, from); + igraph_vector_int_push_back(&edges, to); + } + + } + RNG_END(); + + IGRAPH_CHECK(igraph_create(graph, &edges, n, directed)); + igraph_vector_int_destroy(&edges); + IGRAPH_FINALLY_CLEAN(1); + + return IGRAPH_SUCCESS; +} + /** * \function igraph_bipartite_game_gnm * \brief Generate a random bipartite graph with a fixed number of edges. @@ -1157,6 +1232,8 @@ igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t * * \c IGRAPH_ALL, then each edge direction is considered * independently and mutual edges might be generated. This * argument is ignored for undirected graphs. + * \param multiple Boolean, whether it is allowed to generate more + * than one edge between the same pair of vertices. * \return Error code. * * \sa \ref igraph_erdos_renyi_game_gnm() for the unipartite version, @@ -1169,7 +1246,7 @@ igraph_error_t igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t * igraph_error_t igraph_bipartite_game_gnm(igraph_t *graph, igraph_vector_bool_t *types, igraph_integer_t n1, igraph_integer_t n2, igraph_integer_t m, igraph_bool_t directed, - igraph_neimode_t mode) { + igraph_neimode_t mode, igraph_bool_t multiple) { igraph_vector_int_t edges; igraph_vector_t s; igraph_integer_t n; @@ -1199,6 +1276,11 @@ igraph_error_t igraph_bipartite_game_gnm(igraph_t *graph, igraph_vector_bool_t * } IGRAPH_CHECK(igraph_empty(graph, n, directed)); } else { + + if (multiple) { + return igraph_i_bipartite_game_gnm_multi(graph, types, n1, n2, m, directed, mode); + } + igraph_integer_t i; igraph_real_t maxedges; @@ -1319,7 +1401,7 @@ igraph_error_t igraph_bipartite_game(igraph_t *graph, igraph_vector_bool_t *type if (type == IGRAPH_ERDOS_RENYI_GNP) { return igraph_bipartite_game_gnp(graph, types, n1, n2, p, directed, mode); } else if (type == IGRAPH_ERDOS_RENYI_GNM) { - return igraph_bipartite_game_gnm(graph, types, n1, n2, m, directed, mode); + return igraph_bipartite_game_gnm(graph, types, n1, n2, m, directed, mode, IGRAPH_NO_MULTIPLE); } else { IGRAPH_ERROR("Invalid bipartite game type.", IGRAPH_EINVAL); } diff --git a/src/vendor/cigraph/src/misc/cocitation.c b/src/vendor/cigraph/src/misc/cocitation.c index a73253f58f1..0ffc2a56094 100644 --- a/src/vendor/cigraph/src/misc/cocitation.c +++ b/src/vendor/cigraph/src/misc/cocitation.c @@ -297,9 +297,11 @@ static igraph_error_t igraph_i_neisets_intersect( * \param graph The graph object to analyze * \param res Pointer to a matrix, the result of the calculation will * be stored here. The number of its rows and columns is the same - * as the number of vertex IDs in \p vids. - * \param vids The vertex IDs of the vertices for which the - * calculation will be done. + * as the number of vertex IDs in \p vit_from and \p vit_to, respectively. + * \param vit_from The vertex IDs of the first set of vertices of the + * pairs for which the calculation will be done. + * \param vit_to The vertex IDs of the second set of vertices of the + * pairs for which the calculation will be done. * \param mode The type of neighbors to be used for the calculation in * directed graphs. Possible values: * \clist @@ -333,27 +335,27 @@ static igraph_error_t igraph_i_neisets_intersect( * \example examples/simple/igraph_similarity.c */ igraph_error_t igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t vids, igraph_neimode_t mode, igraph_bool_t loops) { + const igraph_vs_t from, const igraph_vs_t to, igraph_neimode_t mode, igraph_bool_t loops) { igraph_lazy_adjlist_t al; - igraph_vit_t vit, vit2; + igraph_vit_t vit_from, vit_to; igraph_integer_t i, j; igraph_integer_t len_union, len_intersection; igraph_vector_int_t *v1, *v2; igraph_integer_t k; - IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit)); - IGRAPH_FINALLY(igraph_vit_destroy, &vit); - IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit2)); - IGRAPH_FINALLY(igraph_vit_destroy, &vit2); + IGRAPH_CHECK(igraph_vit_create(graph, from, &vit_from)); + IGRAPH_FINALLY(igraph_vit_destroy, &vit_from); + IGRAPH_CHECK(igraph_vit_create(graph, to, &vit_to)); + IGRAPH_FINALLY(igraph_vit_destroy, &vit_to); IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &al, mode, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE)); IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &al); - IGRAPH_CHECK(igraph_matrix_resize(res, IGRAPH_VIT_SIZE(vit), IGRAPH_VIT_SIZE(vit))); + IGRAPH_CHECK(igraph_matrix_resize(res, IGRAPH_VIT_SIZE(vit_from), IGRAPH_VIT_SIZE(vit_to))); if (loops) { - for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) { - i = IGRAPH_VIT_GET(vit); + for (IGRAPH_VIT_RESET(vit_from); !IGRAPH_VIT_END(vit_from); IGRAPH_VIT_NEXT(vit_from)) { + i = IGRAPH_VIT_GET(vit_from); v1 = igraph_lazy_adjlist_get(&al, i); IGRAPH_CHECK_OOM(v1, "Failed to query neighbors."); if (!igraph_vector_int_binsearch(v1, i, &k)) { @@ -362,18 +364,18 @@ igraph_error_t igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t } } - for (IGRAPH_VIT_RESET(vit), i = 0; - !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) { + for (IGRAPH_VIT_RESET(vit_from), i = 0; + !IGRAPH_VIT_END(vit_from); IGRAPH_VIT_NEXT(vit_from), i++) { MATRIX(*res, i, i) = 1.0; - for (IGRAPH_VIT_RESET(vit2), j = 0; - !IGRAPH_VIT_END(vit2); IGRAPH_VIT_NEXT(vit2), j++) { + for (IGRAPH_VIT_RESET(vit_to), j = 0; + !IGRAPH_VIT_END(vit_to); IGRAPH_VIT_NEXT(vit_to), j++) { if (j <= i) { continue; } - v1 = igraph_lazy_adjlist_get(&al, IGRAPH_VIT_GET(vit)); + v1 = igraph_lazy_adjlist_get(&al, IGRAPH_VIT_GET(vit_from)); IGRAPH_CHECK_OOM(v1, "Failed to query neighbors."); - v2 = igraph_lazy_adjlist_get(&al, IGRAPH_VIT_GET(vit2)); + v2 = igraph_lazy_adjlist_get(&al, IGRAPH_VIT_GET(vit_to)); IGRAPH_CHECK_OOM(v2, "Failed to query neighbors."); IGRAPH_CHECK(igraph_i_neisets_intersect(v1, v2, &len_union, &len_intersection)); @@ -387,8 +389,8 @@ igraph_error_t igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t } igraph_lazy_adjlist_destroy(&al); - igraph_vit_destroy(&vit); - igraph_vit_destroy(&vit2); + igraph_vit_destroy(&vit_from); + igraph_vit_destroy(&vit_to); IGRAPH_FINALLY_CLEAN(3); return IGRAPH_SUCCESS; @@ -593,9 +595,11 @@ igraph_error_t igraph_similarity_jaccard_es(const igraph_t *graph, igraph_vector * \param graph The graph object to analyze. * \param res Pointer to a matrix, the result of the calculation will * be stored here. The number of its rows and columns is the same - * as the number of vertex IDs in \p vids. - * \param vids The vertex IDs of the vertices for which the - * calculation will be done. + * as the number of vertex IDs in \p vit_from and \p vit_to, respectively. + * \param vit_from The vertex IDs of the first vertices of the + * pairs for which the calculation will be done. + * \param vit_to The vertex IDs of the second vertices of the + * pairs for which the calculation will be done. * \param mode The type of neighbors to be used for the calculation in * directed graphs. Possible values: * \clist @@ -629,10 +633,10 @@ igraph_error_t igraph_similarity_jaccard_es(const igraph_t *graph, igraph_vector * \example examples/simple/igraph_similarity.c */ igraph_error_t igraph_similarity_dice(const igraph_t *graph, igraph_matrix_t *res, - const igraph_vs_t vids, + const igraph_vs_t vit_from, const igraph_vs_t vit_to, igraph_neimode_t mode, igraph_bool_t loops) { - IGRAPH_CHECK(igraph_similarity_jaccard(graph, res, vids, mode, loops)); + IGRAPH_CHECK(igraph_similarity_jaccard(graph, res, vit_from, vit_to, mode, loops)); igraph_integer_t nr = igraph_matrix_nrow(res); igraph_integer_t nc = igraph_matrix_ncol(res); diff --git a/src/vendor/cigraph/src/misc/conversion.c b/src/vendor/cigraph/src/misc/conversion.c index a1caa0a2f0c..3dca1b6ec38 100644 --- a/src/vendor/cigraph/src/misc/conversion.c +++ b/src/vendor/cigraph/src/misc/conversion.c @@ -450,8 +450,7 @@ igraph_error_t igraph_to_directed(igraph_t *graph, no_of_nodes, IGRAPH_DIRECTED)); IGRAPH_FINALLY(igraph_destroy, &newgraph); - IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph); - IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, true, true, true); + IGRAPH_CHECK(igraph_i_attribute_copy(&newgraph, graph, true, true, true)); igraph_vector_int_destroy(&edges); IGRAPH_FINALLY_CLEAN(2); @@ -483,8 +482,7 @@ igraph_error_t igraph_to_directed(igraph_t *graph, no_of_nodes, IGRAPH_DIRECTED)); IGRAPH_FINALLY(igraph_destroy, &newgraph); - IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph); - IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, true, true, /*edges=*/false); + IGRAPH_CHECK(igraph_i_attribute_copy(&newgraph, graph, true, true, /* edges= */ false)); IGRAPH_CHECK(igraph_i_attribute_permute_edges(graph, &newgraph, &index)); igraph_vector_int_destroy(&index); @@ -584,8 +582,7 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, IGRAPH_UNDIRECTED)); IGRAPH_FINALLY(igraph_destroy, &newgraph); igraph_vector_int_destroy(&edges); - IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph); - IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, true, true, true); + IGRAPH_CHECK(igraph_i_attribute_copy(&newgraph, graph, true, true, true)); IGRAPH_FINALLY_CLEAN(2); igraph_destroy(graph); *graph = newgraph; @@ -682,8 +679,7 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, IGRAPH_UNDIRECTED)); IGRAPH_FINALLY(igraph_destroy, &newgraph); igraph_vector_int_destroy(&edges); - IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph); - IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, true, true, /*edges*/ false); /* no edge attributes */ + IGRAPH_CHECK(igraph_i_attribute_copy(&newgraph, graph, true, true, /* edges= */ false)); if (attr) { igraph_fixed_vectorlist_t vl; @@ -772,8 +768,7 @@ igraph_error_t igraph_to_undirected(igraph_t *graph, IGRAPH_UNDIRECTED)); IGRAPH_FINALLY(igraph_destroy, &newgraph); igraph_vector_int_destroy(&edges); - IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph); - IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, true, true, /*edges*/ false); /* no edge attributes */ + IGRAPH_CHECK(igraph_i_attribute_copy(&newgraph, graph, true, true, /* edges= */ false)); if (attr) { igraph_fixed_vectorlist_t vl; diff --git a/src/vendor/cigraph/src/misc/cycle_bases.c b/src/vendor/cigraph/src/misc/cycle_bases.c index 425a62cf5dd..811f95b9dfd 100644 --- a/src/vendor/cigraph/src/misc/cycle_bases.c +++ b/src/vendor/cigraph/src/misc/cycle_bases.c @@ -346,7 +346,7 @@ static igraph_error_t gaussian_elimination(igraph_vector_int_list_t *reduced_mat IGRAPH_FINALLY_CLEAN(2); return IGRAPH_SUCCESS; } - IGRAPH_CHECK(igraph_vector_int_swap(&work, &tmp)); + igraph_vector_int_swap(&work, &tmp); } else { /* VECTOR(*row)[0] > VECTOR(work)[0] */ break; } diff --git a/src/vendor/cigraph/src/misc/microscopic_update.c b/src/vendor/cigraph/src/misc/microscopic_update.c index 25a0936b072..efd99763cf1 100644 --- a/src/vendor/cigraph/src/misc/microscopic_update.c +++ b/src/vendor/cigraph/src/misc/microscopic_update.c @@ -601,7 +601,7 @@ igraph_error_t igraph_deterministic_optimal_imitation(const igraph_t *graph, /* at random. */ IGRAPH_VECTOR_INT_INIT_FINALLY(&adj, 0); IGRAPH_CHECK(igraph_neighbors(graph, &adj, vid, mode)); - IGRAPH_CHECK(igraph_vector_int_shuffle(&adj)); + igraph_vector_int_shuffle(&adj); /* maximum deterministic imitation */ i = vid; q = VECTOR(*quantities)[vid]; diff --git a/src/vendor/cigraph/src/operators/complementer.c b/src/vendor/cigraph/src/operators/complementer.c index f6a41c6327a..4944943ee37 100644 --- a/src/vendor/cigraph/src/operators/complementer.c +++ b/src/vendor/cigraph/src/operators/complementer.c @@ -95,8 +95,7 @@ igraph_error_t igraph_complementer(igraph_t *res, const igraph_t *graph, IGRAPH_CHECK(igraph_create(res, &edges, no_of_nodes, igraph_is_directed(graph))); igraph_vector_int_destroy(&edges); igraph_vector_int_destroy(&neis); - IGRAPH_I_ATTRIBUTE_DESTROY(res); - IGRAPH_I_ATTRIBUTE_COPY(res, graph, /*graph=*/true, /*vertex=*/true, /*edge=*/false); + IGRAPH_CHECK(igraph_i_attribute_copy(res, graph, true, true, /* edges= */ false)); IGRAPH_FINALLY_CLEAN(2); return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/operators/connect_neighborhood.c b/src/vendor/cigraph/src/operators/connect_neighborhood.c index ce56ffe5735..01974c37f79 100644 --- a/src/vendor/cigraph/src/operators/connect_neighborhood.c +++ b/src/vendor/cigraph/src/operators/connect_neighborhood.c @@ -218,8 +218,7 @@ igraph_error_t igraph_graph_power(const igraph_t *graph, igraph_t *res, } IGRAPH_CHECK(igraph_empty(res, no_of_nodes, dir)); - IGRAPH_I_ATTRIBUTE_DESTROY(res); - IGRAPH_I_ATTRIBUTE_COPY(res, graph, /* graph */ true, /* vertex */ true, /* edge */ false); + IGRAPH_CHECK(igraph_i_attribute_copy(res, graph, true, true, /* edges= */ false)); if (order == 0) { return IGRAPH_SUCCESS; } diff --git a/src/vendor/cigraph/src/operators/contract.c b/src/vendor/cigraph/src/operators/contract.c index 4413ac5022c..90a5afe5698 100644 --- a/src/vendor/cigraph/src/operators/contract.c +++ b/src/vendor/cigraph/src/operators/contract.c @@ -114,8 +114,7 @@ igraph_error_t igraph_contract_vertices(igraph_t *graph, IGRAPH_FINALLY(igraph_destroy, &res); - IGRAPH_I_ATTRIBUTE_DESTROY(&res); - IGRAPH_I_ATTRIBUTE_COPY(&res, graph, /*graph=*/ true, /*vertex=*/ false, /*edge=*/ true); + IGRAPH_CHECK(igraph_i_attribute_copy(&res, graph, true, /* vertex= */ false, true)); if (vattr) { igraph_vector_int_list_t merges; diff --git a/src/vendor/cigraph/src/operators/difference.c b/src/vendor/cigraph/src/operators/difference.c index f9c5786d65a..094e97e2847 100644 --- a/src/vendor/cigraph/src/operators/difference.c +++ b/src/vendor/cigraph/src/operators/difference.c @@ -171,8 +171,7 @@ igraph_error_t igraph_difference(igraph_t *res, /* Attributes */ if (orig->attr) { - IGRAPH_I_ATTRIBUTE_DESTROY(res); - IGRAPH_I_ATTRIBUTE_COPY(res, orig, /*graph=*/ true, /*vertex=*/ true, /*edge=*/ false); + IGRAPH_CHECK(igraph_i_attribute_copy(res, orig, true, true, /* edge= */ false)); IGRAPH_CHECK(igraph_i_attribute_permute_edges(orig, res, &edge_ids)); } diff --git a/src/vendor/cigraph/src/operators/permute.c b/src/vendor/cigraph/src/operators/permute.c index 3fcfb3b8846..7742eb1963b 100644 --- a/src/vendor/cigraph/src/operators/permute.c +++ b/src/vendor/cigraph/src/operators/permute.c @@ -110,8 +110,7 @@ igraph_error_t igraph_permute_vertices(const igraph_t *graph, igraph_t *res, /* Attributes */ if (graph->attr) { igraph_vector_int_t vtypes; - IGRAPH_I_ATTRIBUTE_DESTROY(res); - IGRAPH_I_ATTRIBUTE_COPY(res, graph, /*graph=*/1, /*vertex=*/0, /*edge=*/1); + IGRAPH_CHECK(igraph_i_attribute_copy(res, graph, true, /* vertex= */ false, true)); IGRAPH_VECTOR_INT_INIT_FINALLY(&vtypes, 0); IGRAPH_CHECK(igraph_i_attribute_get_info(graph, 0, 0, 0, &vtypes, 0, 0)); if (igraph_vector_int_size(&vtypes) != 0) { diff --git a/src/vendor/cigraph/src/operators/reverse.c b/src/vendor/cigraph/src/operators/reverse.c index ff1c011b9bd..0bf4a91ba67 100644 --- a/src/vendor/cigraph/src/operators/reverse.c +++ b/src/vendor/cigraph/src/operators/reverse.c @@ -88,8 +88,7 @@ igraph_error_t igraph_reverse_edges(igraph_t *graph, const igraph_es_t eids) { IGRAPH_CHECK(igraph_create(&new_graph, &edges, no_of_nodes, IGRAPH_DIRECTED)); IGRAPH_FINALLY(igraph_destroy, &new_graph); - IGRAPH_I_ATTRIBUTE_DESTROY(&new_graph); - IGRAPH_I_ATTRIBUTE_COPY(&new_graph, graph, 1, 1, 1); /* does IGRAPH_CHECK */ + IGRAPH_CHECK(igraph_i_attribute_copy(&new_graph, graph, true, true, true)); igraph_eit_destroy(&eit); igraph_vector_int_destroy(&edges); diff --git a/src/vendor/cigraph/src/operators/rewire_edges.c b/src/vendor/cigraph/src/operators/rewire_edges.c index 6c5b856bfe2..d6f6585e65d 100644 --- a/src/vendor/cigraph/src/operators/rewire_edges.c +++ b/src/vendor/cigraph/src/operators/rewire_edges.c @@ -274,8 +274,7 @@ igraph_error_t igraph_rewire_edges(igraph_t *graph, igraph_real_t prob, IGRAPH_FINALLY_CLEAN(1); IGRAPH_FINALLY(igraph_destroy, &newgraph); - IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph); - IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, 1, 1, 1); + IGRAPH_CHECK(igraph_i_attribute_copy(&newgraph, graph, true, true, true)); IGRAPH_FINALLY_CLEAN(1); igraph_destroy(graph); *graph = newgraph; @@ -381,8 +380,7 @@ igraph_error_t igraph_rewire_directed_edges(igraph_t *graph, igraph_real_t prob, IGRAPH_FINALLY_CLEAN(1); IGRAPH_FINALLY(igraph_destroy, &newgraph); - IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph); - IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, 1, 1, 1); + IGRAPH_CHECK(igraph_i_attribute_copy(&newgraph, graph, true, true, true)); IGRAPH_FINALLY_CLEAN(1); igraph_destroy(graph); *graph = newgraph; diff --git a/src/vendor/cigraph/src/operators/simplify.c b/src/vendor/cigraph/src/operators/simplify.c index 2ae746b4ac1..c6481e5242a 100644 --- a/src/vendor/cigraph/src/operators/simplify.c +++ b/src/vendor/cigraph/src/operators/simplify.c @@ -172,8 +172,7 @@ igraph_error_t igraph_simplify(igraph_t *graph, IGRAPH_FINALLY(igraph_destroy, &res); - IGRAPH_I_ATTRIBUTE_DESTROY(&res); - IGRAPH_I_ATTRIBUTE_COPY(&res, graph, /*graph=*/ true, /*vertex=*/ true, /*edge=*/ false); + IGRAPH_CHECK(igraph_i_attribute_copy(&res, graph, true, true, /* edges= */ false)); if (attr) { igraph_fixed_vectorlist_t vl; diff --git a/src/vendor/cigraph/src/operators/subgraph.c b/src/vendor/cigraph/src/operators/subgraph.c index d20dfd9eb0e..134a70cd7a0 100644 --- a/src/vendor/cigraph/src/operators/subgraph.c +++ b/src/vendor/cigraph/src/operators/subgraph.c @@ -82,7 +82,7 @@ static igraph_error_t igraph_i_induced_subgraph_copy_and_delete( IGRAPH_CHECK(igraph_copy(res, graph)); IGRAPH_FINALLY(igraph_destroy, res); - IGRAPH_CHECK(igraph_delete_vertices_idx(res, igraph_vss_vector(&delete), + IGRAPH_CHECK(igraph_delete_vertices_map(res, igraph_vss_vector(&delete), map, invmap)); igraph_vector_int_destroy(&delete); @@ -137,10 +137,11 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( my_vids_old2new = map; if (!map_is_prepared) { IGRAPH_CHECK(igraph_vector_int_resize(map, no_of_nodes)); - igraph_vector_int_null(map); + igraph_vector_int_fill(map, -1); } } else { IGRAPH_VECTOR_INT_INIT_FINALLY(&vids_old2new, no_of_nodes); + igraph_vector_int_fill(&vids_old2new, -1); } IGRAPH_VECTOR_INT_INIT_FINALLY(&vids_vec, 0); @@ -166,10 +167,10 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( /* Cater for duplicate vertex IDs in the input vertex selector; we use * the first occurrence of each vertex ID and ignore the rest */ - if (VECTOR(*my_vids_old2new)[vid] == 0) { + if (VECTOR(*my_vids_old2new)[vid] < 0) { IGRAPH_CHECK(igraph_vector_int_push_back(my_vids_new2old, vid)); - no_of_new_nodes++; VECTOR(*my_vids_old2new)[vid] = no_of_new_nodes; + no_of_new_nodes++; } } igraph_vector_int_destroy(&vids_vec); @@ -190,12 +191,12 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( eid = VECTOR(nei_edges)[j]; to = VECTOR(*my_vids_old2new)[ IGRAPH_TO(graph, eid) ]; - if (!to) { + if (to < 0) { continue; } IGRAPH_CHECK(igraph_vector_int_push_back(&new_edges, new_vid)); - IGRAPH_CHECK(igraph_vector_int_push_back(&new_edges, to - 1)); + IGRAPH_CHECK(igraph_vector_int_push_back(&new_edges, to)); IGRAPH_CHECK(igraph_vector_int_push_back(&eids_new2old, eid)); } } else { @@ -212,10 +213,9 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( } to = VECTOR(*my_vids_old2new)[ IGRAPH_TO(graph, eid) ]; - if (!to) { + if (to < 0) { continue; } - to -= 1; if (new_vid == to) { /* this is a loop edge; check whether we need to skip it */ @@ -242,7 +242,6 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( /* Create the new graph */ IGRAPH_CHECK(igraph_create(res, &new_edges, no_of_new_nodes, directed)); - IGRAPH_I_ATTRIBUTE_DESTROY(res); /* Now we can also get rid of the new_edges vector */ igraph_vector_int_destroy(&new_edges); @@ -253,8 +252,7 @@ static igraph_error_t igraph_i_induced_subgraph_create_from_scratch( IGRAPH_FINALLY(igraph_destroy, res); /* Copy the graph attributes */ - IGRAPH_CHECK(igraph_i_attribute_copy(res, graph, - /* ga = */ 1, /* va = */ 0, /* ea = */ 0)); + IGRAPH_CHECK(igraph_i_attribute_copy(res, graph, true, /* vertex= */ false, /* edge= */ false)); /* Copy the vertex attributes */ IGRAPH_CHECK(igraph_i_attribute_permute_vertices(graph, res, my_vids_new2old)); @@ -406,12 +404,12 @@ igraph_error_t igraph_i_induced_subgraph_map(const igraph_t *graph, igraph_t *re * two methods automatically based on the ratio of the number * of vertices in the new and the old graph. * \param map Returns a map of the vertices in \p graph to the vertices - * in \p res. A 0 indicates a vertex is not mapped. An \c i + 1 at + * in \p res. -1 indicates a vertex is not mapped. A value of \c i at * position \c j indicates the vertex \c j in \p graph is mapped * to vertex i in \p res. * \param invmap Returns a map of the vertices in \p res to the vertices - * in \p graph. An i at position \c j indicates the vertex \c i - * in \p graph is mapped to vertex j in \p res. + * in \p graph. A value of \c i at position \c j indicates that + * vertex \c i in \p graph is mapped to vertex \c j in \p res. * * \return Error code: * \c IGRAPH_ENOMEM, not enough memory for @@ -437,7 +435,7 @@ igraph_error_t igraph_induced_subgraph_map(const igraph_t *graph, igraph_t *res, /** * \function igraph_induced_subgraph_edges - * \brief The edges contained within an induced subgraph. + * \brief The edges contained within an induced sugraph. * * This function finds the IDs of those edges which connect vertices from * a given list, passed in the \p vids parameter. @@ -505,7 +503,7 @@ igraph_error_t igraph_induced_subgraph_edges(const igraph_t *graph, igraph_vs_t /** * \ingroup structural * \function igraph_subgraph_edges - * \brief Creates a subgraph with the specified edges and their endpoints (deprecated alias). + * \brief Creates a subgraph with the specified edges and their endpoints. * * \deprecated-by igraph_subgraph_from_edges 0.10.3 */ @@ -521,6 +519,7 @@ igraph_error_t igraph_subgraph_edges( * \function igraph_subgraph_from_edges * \brief Creates a subgraph with the specified edges and their endpoints. * + * * This function collects the specified edges and their endpoints to a new * graph. As the edge IDs in a graph always start with zero, this function * very likely needs to reassign IDs to the edges. Vertex IDs may also be diff --git a/src/vendor/cigraph/src/paths/bellman_ford.c b/src/vendor/cigraph/src/paths/bellman_ford.c index 0b02c0c3ea2..d7d52ba54c7 100644 --- a/src/vendor/cigraph/src/paths/bellman_ford.c +++ b/src/vendor/cigraph/src/paths/bellman_ford.c @@ -580,12 +580,12 @@ igraph_error_t igraph_get_shortest_path_bellman_ford(const igraph_t *graph, /* We use the constant time vector_swap() instead of the linear-time vector_update() to move the result to the output parameter. */ if (edges) { - IGRAPH_CHECK(igraph_vector_int_swap(edges, igraph_vector_int_list_get_ptr(&edges2, 0))); + igraph_vector_int_swap(edges, igraph_vector_int_list_get_ptr(&edges2, 0)); igraph_vector_int_list_destroy(&edges2); IGRAPH_FINALLY_CLEAN(1); } if (vertices) { - IGRAPH_CHECK(igraph_vector_int_swap(vertices, igraph_vector_int_list_get_ptr(&vertices2, 0))); + igraph_vector_int_swap(vertices, igraph_vector_int_list_get_ptr(&vertices2, 0)); igraph_vector_int_list_destroy(&vertices2); IGRAPH_FINALLY_CLEAN(1); } diff --git a/src/vendor/cigraph/src/paths/dijkstra.c b/src/vendor/cigraph/src/paths/dijkstra.c index 3f5fa24f9e9..9ccfcb79c43 100644 --- a/src/vendor/cigraph/src/paths/dijkstra.c +++ b/src/vendor/cigraph/src/paths/dijkstra.c @@ -696,12 +696,12 @@ igraph_error_t igraph_get_shortest_path_dijkstra(const igraph_t *graph, /* We use the constant time vector_swap() instead of the linear-time vector_update() to move the result to the output parameter. */ if (edges) { - IGRAPH_CHECK(igraph_vector_int_swap(edges, igraph_vector_int_list_get_ptr(&edges2, 0))); + igraph_vector_int_swap(edges, igraph_vector_int_list_get_ptr(&edges2, 0)); igraph_vector_int_list_destroy(&edges2); IGRAPH_FINALLY_CLEAN(1); } if (vertices) { - IGRAPH_CHECK(igraph_vector_int_swap(vertices, igraph_vector_int_list_get_ptr(&vertices2, 0))); + igraph_vector_int_swap(vertices, igraph_vector_int_list_get_ptr(&vertices2, 0)); igraph_vector_int_list_destroy(&vertices2); IGRAPH_FINALLY_CLEAN(1); } diff --git a/src/vendor/cigraph/src/paths/johnson.c b/src/vendor/cigraph/src/paths/johnson.c index fdd09ffc8a0..ea9c7eac6f9 100644 --- a/src/vendor/cigraph/src/paths/johnson.c +++ b/src/vendor/cigraph/src/paths/johnson.c @@ -66,7 +66,12 @@ * vertex twice or more. * \param weights Optional edge weights. If it is a null-pointer, then * the unweighted breadth-first search based \ref igraph_distances() will - * be called. Edges with positive infinite weights are ignored. + * be called. Edges with positive infinite weights are ignored. + * \param mode For directed graphs; whether to follow paths along edge + * directions (\c IGRAPH_OUT), or the opposite (\c IGRAPH_IN), or + * ignore edge directions completely (\c IGRAPH_ALL). It is ignored + * for undirected graphs. \c IGRAPH_ALL should not be used with + * negative weights. * \return Error code. * * Time complexity: O(s|V|log|V|+|V||E|), |V| and |E| are the number @@ -81,7 +86,8 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, igraph_matrix_t *res, const igraph_vs_t from, const igraph_vs_t to, - const igraph_vector_t *weights) { + const igraph_vector_t *weights, + igraph_neimode_t mode) { igraph_integer_t no_of_nodes = igraph_vcount(graph); igraph_integer_t no_of_edges = igraph_ecount(graph); @@ -96,7 +102,7 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, /* If no weights, then we can just run the unweighted version */ if (!weights) { - return igraph_distances(graph, res, from, to, IGRAPH_OUT); + return igraph_distances(graph, res, from, to, mode); } if (igraph_vector_size(weights) != no_of_edges) { @@ -107,7 +113,7 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, /* If no edges, then we can just run the unweighted version */ if (no_of_edges == 0) { - return igraph_distances(graph, res, from, to, IGRAPH_OUT); + return igraph_distances(graph, res, from, to, mode); } /* If no negative weights, then we can run Dijkstra's algorithm */ @@ -117,13 +123,13 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, IGRAPH_ERROR("Weight vector must not contain NaN values.", IGRAPH_EINVAL); } if (min_weight >= 0) { - return igraph_distances_dijkstra(graph, res, from, to, weights, IGRAPH_OUT); + return igraph_distances_dijkstra(graph, res, from, to, weights, mode); } } - if (!igraph_is_directed(graph)) { - IGRAPH_ERROR("Johnson's shortest path: undirected graph and negative weight.", - IGRAPH_EINVAL); + if (!igraph_is_directed(graph) || mode == IGRAPH_ALL) { + IGRAPH_ERROR("Undirected graph with negative weight.", + IGRAPH_ENEGLOOP); } /* ------------------------------------------------------------ */ @@ -142,9 +148,16 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, IGRAPH_VECTOR_INT_INIT_FINALLY(&edges, no_edges_reserved); igraph_get_edgelist(graph, &edges, /*bycol=*/ 0); /* reserved */ igraph_vector_int_resize(&edges, no_edges_reserved); /* reserved */ - for (i = 0, ptr = no_of_edges * 2; i < no_of_nodes; i++) { - VECTOR(edges)[ptr++] = no_of_nodes; - VECTOR(edges)[ptr++] = i; + if (mode == IGRAPH_OUT) { + for (i = 0, ptr = no_of_edges * 2; i < no_of_nodes; i++) { + VECTOR(edges)[ptr++] = no_of_nodes; + VECTOR(edges)[ptr++] = i; + } + } else { + for (i = 0, ptr = no_of_edges * 2; i < no_of_nodes; i++) { + VECTOR(edges)[ptr++] = i; + VECTOR(edges)[ptr++] = no_of_nodes; + } } IGRAPH_CHECK(igraph_add_edges(&newgraph, &edges, 0)); igraph_vector_int_destroy(&edges); @@ -162,7 +175,7 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, IGRAPH_CHECK(igraph_distances_bellman_ford(&newgraph, &bfres, igraph_vss_1(no_of_nodes), - igraph_vss_all(), &newweights, IGRAPH_OUT)); + igraph_vss_all(), &newweights, mode)); igraph_destroy(&newgraph); IGRAPH_FINALLY_CLEAN(1); @@ -175,7 +188,11 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, for (i = 0; i < no_of_edges; i++) { igraph_integer_t ffrom = IGRAPH_FROM(graph, i); igraph_integer_t tto = IGRAPH_TO(graph, i); - VECTOR(newweights)[i] += MATRIX(bfres, 0, ffrom) - MATRIX(bfres, 0, tto); + if (mode == IGRAPH_OUT) { + VECTOR(newweights)[i] += MATRIX(bfres, 0, ffrom) - MATRIX(bfres, 0, tto); + } else { + VECTOR(newweights)[i] += MATRIX(bfres, 0, tto) - MATRIX(bfres, 0, ffrom); + } /* If a weight becomes slightly negative due to roundoff errors, snap it to exact zero. */ @@ -185,7 +202,7 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, /* Run Dijkstra's algorithm on the new weights */ IGRAPH_CHECK(igraph_distances_dijkstra(graph, res, from, to, &newweights, - IGRAPH_OUT)); + mode)); igraph_vector_destroy(&newweights); IGRAPH_FINALLY_CLEAN(1); @@ -202,8 +219,14 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, if (igraph_vs_is_all(&to)) { igraph_integer_t v2; for (v2 = 0; v2 < nc; v2++) { - igraph_real_t sub = MATRIX(bfres, 0, v1) - MATRIX(bfres, 0, v2); - MATRIX(*res, i, v2) -= sub; + igraph_real_t sub; + if (mode == IGRAPH_OUT) { + sub = MATRIX(bfres, 0, v1) - MATRIX(bfres, 0, v2); + MATRIX(*res, i, v2) -= sub; + } else { + sub = MATRIX(bfres, 0, v2) - MATRIX(bfres, 0, v1); + MATRIX(*res, v2, i) -= sub; + } } } else { igraph_integer_t j; @@ -211,9 +234,15 @@ igraph_error_t igraph_distances_johnson(const igraph_t *graph, IGRAPH_CHECK(igraph_vit_create(graph, to, &tovit)); IGRAPH_FINALLY(igraph_vit_destroy, &tovit); for (j = 0, IGRAPH_VIT_RESET(tovit); j < nc; j++, IGRAPH_VIT_NEXT(tovit)) { + igraph_real_t sub; igraph_integer_t v2 = IGRAPH_VIT_GET(tovit); - igraph_real_t sub = MATRIX(bfres, 0, v1) - MATRIX(bfres, 0, v2); - MATRIX(*res, i, j) -= sub; + if (mode == IGRAPH_OUT) { + sub = MATRIX(bfres, 0, v1) - MATRIX(bfres, 0, v2); + MATRIX(*res, i, j) -= sub; + } else { + sub = MATRIX(bfres, 0, v2) - MATRIX(bfres, 0, v1); + MATRIX(*res, j, i) -= sub; + } } igraph_vit_destroy(&tovit); IGRAPH_FINALLY_CLEAN(1); @@ -238,5 +267,5 @@ igraph_error_t igraph_shortest_paths_johnson(const igraph_t *graph, const igraph_vs_t from, const igraph_vs_t to, const igraph_vector_t *weights) { - return igraph_distances_johnson(graph, res, from, to, weights); + return igraph_distances_johnson(graph, res, from, to, weights, IGRAPH_OUT); } diff --git a/src/vendor/cigraph/src/paths/unweighted.c b/src/vendor/cigraph/src/paths/unweighted.c index 2bf3affafe7..e412cb6eddf 100644 --- a/src/vendor/cigraph/src/paths/unweighted.c +++ b/src/vendor/cigraph/src/paths/unweighted.c @@ -605,12 +605,12 @@ igraph_error_t igraph_get_shortest_path(const igraph_t *graph, /* We use the constant time vector_swap() instead of the linear-time vector_update() to move the result to the output parameter. */ if (edges) { - IGRAPH_CHECK(igraph_vector_int_swap(edges, igraph_vector_int_list_get_ptr(&edges2, 0))); + igraph_vector_int_swap(edges, igraph_vector_int_list_get_ptr(&edges2, 0)); igraph_vector_int_list_destroy(&edges2); IGRAPH_FINALLY_CLEAN(1); } if (vertices) { - IGRAPH_CHECK(igraph_vector_int_swap(vertices, igraph_vector_int_list_get_ptr(&vertices2, 0))); + igraph_vector_int_swap(vertices, igraph_vector_int_list_get_ptr(&vertices2, 0)); igraph_vector_int_list_destroy(&vertices2); IGRAPH_FINALLY_CLEAN(1); } diff --git a/src/vendor/cigraph/src/random/random.c b/src/vendor/cigraph/src/random/random.c index b5b44451ae3..376af1e4109 100644 --- a/src/vendor/cigraph/src/random/random.c +++ b/src/vendor/cigraph/src/random/random.c @@ -146,32 +146,32 @@ * igraph_rng_set_default() function. */ -extern IGRAPH_THREAD_LOCAL igraph_rng_t igraph_i_rng_default; /* defined in rng_pcg32.c */ +extern igraph_rng_t igraph_i_rng_default; /* defined in rng_pcg32.c */ +IGRAPH_THREAD_LOCAL igraph_rng_t *igraph_i_rng_default_ptr = &igraph_i_rng_default; /** * \function igraph_rng_set_default * \brief Set the default igraph random number generator. * - * This function \em copies the internal structure of the given \type igraph_rng_t - * object to igraph's internal default RNG structure. The structure itself - * contains two pointers only, one to the "methods" of the RNG and one to the - * memory buffer holding the internal state of the RNG. This means that if you - * keep on generating random numbers from the RNG after setting it as the - * default, it will affect the state of the default RNG as well because the two - * share the same state pointer. However, do \em not expect - * \ref igraph_rng_default() to return the same pointer as the one you passed - * in here - the state is shared, but the entire structure is not. + * This function updates the default RNG used by igraph to be the one + * pointed to by \p rng, and returns a pointer to the previous default + * RNG. Future calls to \ref igraph_rng_default() will return the same + * pointer as \p rng. The RNG pointed to by \p rng must not be destroyed + * for as long as it is used as the default. * * \param rng The random number generator to use as default from now * on. Calling \ref igraph_rng_destroy() on it, while it is still * being used as the default will result in crashes and/or * unpredictable results. + * \return Pointer the previous default RNG. * * Time complexity: O(1). */ -void igraph_rng_set_default(igraph_rng_t *rng) { - igraph_i_rng_default = (*rng); +igraph_rng_t *igraph_rng_set_default(igraph_rng_t *rng) { + igraph_rng_t *old_rng = igraph_i_rng_default_ptr; + igraph_i_rng_default_ptr = rng; + return old_rng; } @@ -187,7 +187,7 @@ void igraph_rng_set_default(igraph_rng_t *rng) { */ igraph_rng_t *igraph_rng_default(void) { - return &igraph_i_rng_default; + return igraph_i_rng_default_ptr; } /* ------------------------------------ */ diff --git a/src/vendor/cigraph/src/random/rng_pcg32.c b/src/vendor/cigraph/src/random/rng_pcg32.c index fb51b1ba2f8..7d5655eb4fe 100644 --- a/src/vendor/cigraph/src/random/rng_pcg32.c +++ b/src/vendor/cigraph/src/random/rng_pcg32.c @@ -115,7 +115,7 @@ const igraph_rng_type_t igraph_rngtype_pcg32 = { static pcg32_random_t igraph_i_rng_default_state = PCG32_INITIALIZER; -IGRAPH_THREAD_LOCAL igraph_rng_t igraph_i_rng_default = { +igraph_rng_t igraph_i_rng_default = { addr(igraph_rngtype_pcg32), addr(igraph_i_rng_default_state), /* is_seeded = */ true diff --git a/src/vendor/igraph_version.h b/src/vendor/igraph_version.h index 697724c9e8c..0731e344a94 100644 --- a/src/vendor/igraph_version.h +++ b/src/vendor/igraph_version.h @@ -28,11 +28,11 @@ __BEGIN_DECLS -#define IGRAPH_VERSION "0.10.10-82-g68522c3fb" +#define IGRAPH_VERSION "0.10.10-287-gb13aa4e0b" #define IGRAPH_VERSION_MAJOR 0 #define IGRAPH_VERSION_MINOR 10 #define IGRAPH_VERSION_PATCH 10 -#define IGRAPH_VERSION_PRERELEASE "82-g68522c3fb" +#define IGRAPH_VERSION_PRERELEASE "287-gb13aa4e0b" IGRAPH_EXPORT void igraph_version(const char **version_string, int *major, diff --git a/src/vendor/io/lgl-parser.c b/src/vendor/io/lgl-parser.c index 1218a8a3fb7..ff1fb8cd812 100644 --- a/src/vendor/io/lgl-parser.c +++ b/src/vendor/io/lgl-parser.c @@ -1517,7 +1517,7 @@ YYLTYPE yylloc = yyloc_default; { IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, context->actvertex)); IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, (yyvsp[-1].edgenum))); - IGRAPH_YY_CHECK(igraph_vector_push_back(context->weights, 0)); + IGRAPH_YY_CHECK(igraph_vector_push_back(context->weights, 1.0)); } #line 1523 "src/vendor/io/lgl-parser.c" break; diff --git a/src/vendor/io/ncol-parser.c b/src/vendor/io/ncol-parser.c index 15916ec4094..2c64493ac68 100644 --- a/src/vendor/io/ncol-parser.c +++ b/src/vendor/io/ncol-parser.c @@ -1502,7 +1502,7 @@ YYLTYPE yylloc = yyloc_default; case 5: /* edge: endpoints "end of line" */ #line 97 "src/vendor/cigraph/src/io/ncol-parser.y" { - IGRAPH_YY_CHECK(igraph_vector_push_back(context->weights, 0.0)); + IGRAPH_YY_CHECK(igraph_vector_push_back(context->weights, 1.0)); } #line 1508 "src/vendor/io/ncol-parser.c" break; diff --git a/src/vendor/io/pajek-parser.c b/src/vendor/io/pajek-parser.c index b2e5ae639f4..2a6c3136a23 100644 --- a/src/vendor/io/pajek-parser.c +++ b/src/vendor/io/pajek-parser.c @@ -131,15 +131,17 @@ static igraph_error_t add_numeric_edge_attribute(const char *name, igraph_real_t value, igraph_i_pajek_parsedata_t *context); static igraph_error_t add_numeric_attribute(igraph_trie_t *names, - igraph_vector_ptr_t *attrs, + igraph_attribute_record_list_t *attrs, igraph_integer_t count, const char *attrname, + igraph_real_t default_value, igraph_integer_t vid, igraph_real_t number); static igraph_error_t add_string_attribute(igraph_trie_t *names, - igraph_vector_ptr_t *attrs, + igraph_attribute_record_list_t *attrs, igraph_integer_t count, const char *attrname, + const char *default_value, igraph_integer_t vid, const char *str, igraph_integer_t str_len); @@ -151,11 +153,15 @@ static igraph_error_t make_dynstr(const char *src, size_t len, char **res); static igraph_bool_t is_standard_vattr(const char *attrname); static igraph_bool_t is_standard_eattr(const char *attrname); static igraph_error_t deconflict_attrname(char **attrname); +static igraph_real_t get_default_value_for_numeric_vattr(const char *attrname); +static igraph_real_t get_default_value_for_numeric_eattr(const char *attrname); +static const char* get_default_value_for_string_vattr(const char *attrname); +static const char* get_default_value_for_string_eattr(const char *attrname); #define scanner context->scanner -#line 159 "src/vendor/io/pajek-parser.c" +#line 165 "src/vendor/io/pajek-parser.c" # ifndef YY_CAST # ifdef __cplusplus @@ -678,18 +684,18 @@ static const yytype_int8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = { - 0, 188, 188, 199, 199, 201, 201, 203, 205, 215, - 233, 233, 235, 236, 236, 239, 250, 255, 256, 260, - 266, 266, 270, 270, 273, 274, 277, 280, 283, 286, - 289, 292, 295, 298, 301, 306, 309, 312, 315, 318, - 321, 336, 336, 336, 336, 336, 336, 338, 339, 341, - 341, 343, 343, 348, 349, 351, 351, 353, 353, 358, - 358, 362, 362, 365, 366, 369, 372, 375, 378, 381, - 384, 387, 390, 393, 396, 399, 402, 405, 410, 413, - 416, 419, 422, 425, 428, 443, 445, 445, 447, 449, - 449, 451, 453, 458, 460, 460, 462, 464, 464, 466, - 468, 475, 477, 482, 482, 484, 486, 486, 488, 508, - 516, 524, 528, 530, 532, 534 + 0, 194, 194, 205, 205, 207, 207, 209, 211, 221, + 239, 239, 241, 242, 242, 245, 256, 260, 261, 265, + 271, 271, 275, 275, 278, 279, 282, 285, 288, 291, + 294, 297, 300, 303, 306, 311, 314, 317, 320, 323, + 326, 341, 341, 341, 341, 341, 341, 343, 344, 346, + 346, 348, 348, 353, 354, 356, 356, 358, 358, 363, + 363, 367, 367, 370, 371, 374, 377, 380, 383, 386, + 389, 392, 395, 398, 401, 404, 407, 410, 415, 418, + 421, 424, 427, 430, 433, 448, 450, 450, 452, 454, + 454, 456, 458, 463, 465, 465, 467, 469, 469, 471, + 473, 480, 482, 487, 487, 489, 491, 491, 493, 513, + 521, 529, 533, 535, 537, 539 }; #endif @@ -1486,9 +1492,9 @@ yydestruct (const char *yymsg, switch (yykind) { case YYSYMBOL_parname: /* parname */ -#line 133 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 139 "src/vendor/cigraph/src/io/pajek-parser.y" { free(((*yyvaluep).dynstr)); } -#line 1492 "src/vendor/io/pajek-parser.c" +#line 1498 "src/vendor/io/pajek-parser.c" break; default: @@ -1792,7 +1798,7 @@ YYLTYPE yylloc = yyloc_default; switch (yyn) { case 2: /* input: nethead vertices edgeblock final_newlines */ -#line 188 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 194 "src/vendor/cigraph/src/io/pajek-parser.y" { if (context->vcount2 > 0) { check_bipartite(context); } if (! context->eof) { @@ -1803,11 +1809,11 @@ YYLTYPE yylloc = yyloc_default; } YYACCEPT; /* stop parsing even if there is more data in the file. */ } -#line 1807 "src/vendor/io/pajek-parser.c" +#line 1813 "src/vendor/io/pajek-parser.c" break; case 8: /* verticeshead: "*Vertices line" integer */ -#line 205 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 211 "src/vendor/cigraph/src/io/pajek-parser.y" { context->vcount=(yyvsp[0].intnum); context->vcount2=0; @@ -1818,11 +1824,11 @@ YYLTYPE yylloc = yyloc_default; IGRAPH_YY_ERRORF("Vertex count too large in Pajek file (%" IGRAPH_PRId ").", IGRAPH_EINVAL, context->vcount); } } -#line 1822 "src/vendor/io/pajek-parser.c" +#line 1828 "src/vendor/io/pajek-parser.c" break; case 9: /* verticeshead: "*Vertices line" integer integer */ -#line 215 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 221 "src/vendor/cigraph/src/io/pajek-parser.y" { context->vcount=(yyvsp[-1].intnum); context->vcount2=(yyvsp[0].intnum); @@ -1840,23 +1846,23 @@ YYLTYPE yylloc = yyloc_default; } IGRAPH_YY_CHECK(add_bipartite_type(context)); } -#line 1844 "src/vendor/io/pajek-parser.c" +#line 1850 "src/vendor/io/pajek-parser.c" break; case 13: /* $@1: %empty */ -#line 236 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 242 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actvertex=(yyvsp[0].intnum); } -#line 1850 "src/vendor/io/pajek-parser.c" +#line 1856 "src/vendor/io/pajek-parser.c" break; case 14: /* vertexline: vertex $@1 vertexid vertexcoords shape vertparams "end of line" */ -#line 236 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 242 "src/vendor/cigraph/src/io/pajek-parser.y" { } -#line 1856 "src/vendor/io/pajek-parser.c" +#line 1862 "src/vendor/io/pajek-parser.c" break; case 15: /* vertex: integer */ -#line 239 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 245 "src/vendor/cigraph/src/io/pajek-parser.y" { igraph_integer_t v = (yyvsp[0].intnum); if (v < 1 || v > context->vcount) { @@ -1867,167 +1873,166 @@ YYLTYPE yylloc = yyloc_default; } (yyval.intnum) = v; } -#line 1871 "src/vendor/io/pajek-parser.c" +#line 1877 "src/vendor/io/pajek-parser.c" break; case 16: /* vertexid: word */ -#line 250 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 256 "src/vendor/cigraph/src/io/pajek-parser.y" { - IGRAPH_YY_CHECK(add_string_vertex_attribute("id", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); IGRAPH_YY_CHECK(add_string_vertex_attribute("name", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 1880 "src/vendor/io/pajek-parser.c" +#line 1885 "src/vendor/io/pajek-parser.c" break; case 18: /* vertexcoords: number number */ -#line 256 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 261 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("x", (yyvsp[-1].realnum), context)); IGRAPH_YY_CHECK(add_numeric_vertex_attribute("y", (yyvsp[0].realnum), context)); } -#line 1889 "src/vendor/io/pajek-parser.c" +#line 1894 "src/vendor/io/pajek-parser.c" break; case 19: /* vertexcoords: number number number */ -#line 260 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 265 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("x", (yyvsp[-2].realnum), context)); IGRAPH_YY_CHECK(add_numeric_vertex_attribute("y", (yyvsp[-1].realnum), context)); IGRAPH_YY_CHECK(add_numeric_vertex_attribute("z", (yyvsp[0].realnum), context)); } -#line 1899 "src/vendor/io/pajek-parser.c" +#line 1904 "src/vendor/io/pajek-parser.c" break; case 21: /* shape: word */ -#line 266 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 271 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_vertex_attribute("shape", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 1907 "src/vendor/io/pajek-parser.c" +#line 1912 "src/vendor/io/pajek-parser.c" break; case 25: /* vertparam: VP_X_FACT number */ -#line 274 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 279 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("xfact", (yyvsp[0].realnum), context)); } -#line 1915 "src/vendor/io/pajek-parser.c" +#line 1920 "src/vendor/io/pajek-parser.c" break; case 26: /* vertparam: VP_Y_FACT number */ -#line 277 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 282 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("yfact", (yyvsp[0].realnum), context)); } -#line 1923 "src/vendor/io/pajek-parser.c" +#line 1928 "src/vendor/io/pajek-parser.c" break; case 27: /* vertparam: VP_LR number */ -#line 280 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 285 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("labeldist", (yyvsp[0].realnum), context)); } -#line 1931 "src/vendor/io/pajek-parser.c" +#line 1936 "src/vendor/io/pajek-parser.c" break; case 28: /* vertparam: VP_LPHI number */ -#line 283 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 288 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("labeldegree2", (yyvsp[0].realnum), context)); } -#line 1939 "src/vendor/io/pajek-parser.c" +#line 1944 "src/vendor/io/pajek-parser.c" break; case 29: /* vertparam: VP_BW number */ -#line 286 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 291 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("framewidth", (yyvsp[0].realnum), context)); } -#line 1947 "src/vendor/io/pajek-parser.c" +#line 1952 "src/vendor/io/pajek-parser.c" break; case 30: /* vertparam: VP_FOS number */ -#line 289 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 294 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("fontsize", (yyvsp[0].realnum), context)); } -#line 1955 "src/vendor/io/pajek-parser.c" +#line 1960 "src/vendor/io/pajek-parser.c" break; case 31: /* vertparam: VP_PHI number */ -#line 292 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 297 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("rotation", (yyvsp[0].realnum), context)); } -#line 1963 "src/vendor/io/pajek-parser.c" +#line 1968 "src/vendor/io/pajek-parser.c" break; case 32: /* vertparam: VP_R number */ -#line 295 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 300 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("radius", (yyvsp[0].realnum), context)); } -#line 1971 "src/vendor/io/pajek-parser.c" +#line 1976 "src/vendor/io/pajek-parser.c" break; case 33: /* vertparam: VP_Q number */ -#line 298 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 303 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("diamondratio", (yyvsp[0].realnum), context)); } -#line 1979 "src/vendor/io/pajek-parser.c" +#line 1984 "src/vendor/io/pajek-parser.c" break; case 34: /* vertparam: VP_LA number */ -#line 301 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 306 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_vertex_attribute("labeldegree", (yyvsp[0].realnum), context)); } -#line 1987 "src/vendor/io/pajek-parser.c" +#line 1992 "src/vendor/io/pajek-parser.c" break; case 35: /* vpword: VP_FONT parstrval */ -#line 306 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 311 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_vertex_attribute("font", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 1995 "src/vendor/io/pajek-parser.c" +#line 2000 "src/vendor/io/pajek-parser.c" break; case 36: /* vpword: VP_URL parstrval */ -#line 309 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 314 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_vertex_attribute("url", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 2003 "src/vendor/io/pajek-parser.c" +#line 2008 "src/vendor/io/pajek-parser.c" break; case 37: /* vpword: VP_IC parstrval */ -#line 312 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 317 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_vertex_attribute("color", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 2011 "src/vendor/io/pajek-parser.c" +#line 2016 "src/vendor/io/pajek-parser.c" break; case 38: /* vpword: VP_BC parstrval */ -#line 315 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 320 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_vertex_attribute("framecolor", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 2019 "src/vendor/io/pajek-parser.c" +#line 2024 "src/vendor/io/pajek-parser.c" break; case 39: /* vpword: VP_LC parstrval */ -#line 318 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 323 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_vertex_attribute("labelcolor", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 2027 "src/vendor/io/pajek-parser.c" +#line 2032 "src/vendor/io/pajek-parser.c" break; case 40: /* vpword: parname parstrval */ -#line 321 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 326 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_FINALLY(igraph_free, (yyvsp[-1].dynstr)); if (is_standard_vattr((yyvsp[-1].dynstr))) { @@ -2041,231 +2046,231 @@ YYLTYPE yylloc = yyloc_default; IGRAPH_FREE((yyvsp[-1].dynstr)); IGRAPH_FINALLY_CLEAN(1); } -#line 2045 "src/vendor/io/pajek-parser.c" +#line 2050 "src/vendor/io/pajek-parser.c" break; case 47: /* arcs: "*Arcs line" "end of line" arcsdefs */ -#line 338 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 343 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=true; } -#line 2051 "src/vendor/io/pajek-parser.c" +#line 2056 "src/vendor/io/pajek-parser.c" break; case 48: /* arcs: "*Arcs line" number "end of line" arcsdefs */ -#line 339 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 344 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=true; } -#line 2057 "src/vendor/io/pajek-parser.c" +#line 2062 "src/vendor/io/pajek-parser.c" break; case 51: /* $@2: %empty */ -#line 343 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 348 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actedge++; } -#line 2063 "src/vendor/io/pajek-parser.c" +#line 2068 "src/vendor/io/pajek-parser.c" break; case 52: /* arcsline: vertex vertex $@2 weight edgeparams "end of line" */ -#line 343 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 348 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, (yyvsp[-5].intnum)-1)); IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, (yyvsp[-4].intnum)-1)); } -#line 2071 "src/vendor/io/pajek-parser.c" +#line 2076 "src/vendor/io/pajek-parser.c" break; case 53: /* edges: "*Edges line" "end of line" edgesdefs */ -#line 348 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 353 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=0; } -#line 2077 "src/vendor/io/pajek-parser.c" +#line 2082 "src/vendor/io/pajek-parser.c" break; case 54: /* edges: "*Edges line" number "end of line" edgesdefs */ -#line 349 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 354 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=0; } -#line 2083 "src/vendor/io/pajek-parser.c" +#line 2088 "src/vendor/io/pajek-parser.c" break; case 57: /* $@3: %empty */ -#line 353 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 358 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actedge++; } -#line 2089 "src/vendor/io/pajek-parser.c" +#line 2094 "src/vendor/io/pajek-parser.c" break; case 58: /* edgesline: vertex vertex $@3 weight edgeparams "end of line" */ -#line 353 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 358 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, (yyvsp[-5].intnum)-1)); IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, (yyvsp[-4].intnum)-1)); } -#line 2097 "src/vendor/io/pajek-parser.c" +#line 2102 "src/vendor/io/pajek-parser.c" break; case 60: /* weight: number */ -#line 358 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 363 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("weight", (yyvsp[0].realnum), context)); } -#line 2105 "src/vendor/io/pajek-parser.c" +#line 2110 "src/vendor/io/pajek-parser.c" break; case 64: /* edgeparam: EP_S number */ -#line 366 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 371 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("arrowsize", (yyvsp[0].realnum), context)); } -#line 2113 "src/vendor/io/pajek-parser.c" +#line 2118 "src/vendor/io/pajek-parser.c" break; case 65: /* edgeparam: EP_W number */ -#line 369 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 374 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("edgewidth", (yyvsp[0].realnum), context)); } -#line 2121 "src/vendor/io/pajek-parser.c" +#line 2126 "src/vendor/io/pajek-parser.c" break; case 66: /* edgeparam: EP_H1 number */ -#line 372 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 377 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("hook1", (yyvsp[0].realnum), context)); } -#line 2129 "src/vendor/io/pajek-parser.c" +#line 2134 "src/vendor/io/pajek-parser.c" break; case 67: /* edgeparam: EP_H2 number */ -#line 375 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 380 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("hook2", (yyvsp[0].realnum), context)); } -#line 2137 "src/vendor/io/pajek-parser.c" +#line 2142 "src/vendor/io/pajek-parser.c" break; case 68: /* edgeparam: EP_A1 number */ -#line 378 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 383 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("angle1", (yyvsp[0].realnum), context)); } -#line 2145 "src/vendor/io/pajek-parser.c" +#line 2150 "src/vendor/io/pajek-parser.c" break; case 69: /* edgeparam: EP_A2 number */ -#line 381 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 386 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("angle2", (yyvsp[0].realnum), context)); } -#line 2153 "src/vendor/io/pajek-parser.c" +#line 2158 "src/vendor/io/pajek-parser.c" break; case 70: /* edgeparam: EP_K1 number */ -#line 384 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 389 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("velocity1", (yyvsp[0].realnum), context)); } -#line 2161 "src/vendor/io/pajek-parser.c" +#line 2166 "src/vendor/io/pajek-parser.c" break; case 71: /* edgeparam: EP_K2 number */ -#line 387 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 392 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("velocity2", (yyvsp[0].realnum), context)); } -#line 2169 "src/vendor/io/pajek-parser.c" +#line 2174 "src/vendor/io/pajek-parser.c" break; case 72: /* edgeparam: EP_AP number */ -#line 390 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 395 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("arrowpos", (yyvsp[0].realnum), context)); } -#line 2177 "src/vendor/io/pajek-parser.c" +#line 2182 "src/vendor/io/pajek-parser.c" break; case 73: /* edgeparam: EP_LP number */ -#line 393 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 398 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("labelpos", (yyvsp[0].realnum), context)); } -#line 2185 "src/vendor/io/pajek-parser.c" +#line 2190 "src/vendor/io/pajek-parser.c" break; case 74: /* edgeparam: EP_LR number */ -#line 396 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 401 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("labelangle", (yyvsp[0].realnum), context)); } -#line 2193 "src/vendor/io/pajek-parser.c" +#line 2198 "src/vendor/io/pajek-parser.c" break; case 75: /* edgeparam: EP_LPHI number */ -#line 399 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 404 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("labelangle2", (yyvsp[0].realnum), context)); } -#line 2201 "src/vendor/io/pajek-parser.c" +#line 2206 "src/vendor/io/pajek-parser.c" break; case 76: /* edgeparam: EP_LA number */ -#line 402 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 407 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("labeldegree", (yyvsp[0].realnum), context)); } -#line 2209 "src/vendor/io/pajek-parser.c" +#line 2214 "src/vendor/io/pajek-parser.c" break; case 77: /* edgeparam: EP_FOS number */ -#line 405 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 410 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_numeric_edge_attribute("fontsize", (yyvsp[0].realnum), context)); } -#line 2217 "src/vendor/io/pajek-parser.c" +#line 2222 "src/vendor/io/pajek-parser.c" break; case 78: /* epword: EP_A parstrval */ -#line 410 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 415 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_edge_attribute("arrowtype", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 2225 "src/vendor/io/pajek-parser.c" +#line 2230 "src/vendor/io/pajek-parser.c" break; case 79: /* epword: EP_P parstrval */ -#line 413 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 418 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_edge_attribute("linepattern", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 2233 "src/vendor/io/pajek-parser.c" +#line 2238 "src/vendor/io/pajek-parser.c" break; case 80: /* epword: EP_L parstrval */ -#line 416 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 421 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_edge_attribute("label", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 2241 "src/vendor/io/pajek-parser.c" +#line 2246 "src/vendor/io/pajek-parser.c" break; case 81: /* epword: EP_LC parstrval */ -#line 419 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 424 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_edge_attribute("labelcolor", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 2249 "src/vendor/io/pajek-parser.c" +#line 2254 "src/vendor/io/pajek-parser.c" break; case 82: /* epword: EP_C parstrval */ -#line 422 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 427 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_edge_attribute("color", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 2257 "src/vendor/io/pajek-parser.c" +#line 2262 "src/vendor/io/pajek-parser.c" break; case 83: /* epword: EP_FONT parstrval */ -#line 425 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 430 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(add_string_edge_attribute("font", (yyvsp[0].string).str, (yyvsp[0].string).len, context)); } -#line 2265 "src/vendor/io/pajek-parser.c" +#line 2270 "src/vendor/io/pajek-parser.c" break; case 84: /* epword: parname parstrval */ -#line 428 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 433 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_FINALLY(igraph_free, (yyvsp[-1].dynstr)); if (is_standard_eattr((yyvsp[-1].dynstr))) { @@ -2279,68 +2284,68 @@ YYLTYPE yylloc = yyloc_default; IGRAPH_FREE((yyvsp[-1].dynstr)); IGRAPH_FINALLY_CLEAN(1); } -#line 2283 "src/vendor/io/pajek-parser.c" +#line 2288 "src/vendor/io/pajek-parser.c" break; case 85: /* arcslist: "*Arcslist line" "end of line" arcslistlines */ -#line 443 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 448 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=true; } -#line 2289 "src/vendor/io/pajek-parser.c" +#line 2294 "src/vendor/io/pajek-parser.c" break; case 91: /* arclistfrom: integer */ -#line 451 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 456 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actfrom=labs((yyvsp[0].intnum))-1; } -#line 2295 "src/vendor/io/pajek-parser.c" +#line 2300 "src/vendor/io/pajek-parser.c" break; case 92: /* arclistto: integer */ -#line 453 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 458 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, context->actfrom)); IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, labs((yyvsp[0].intnum))-1)); } -#line 2304 "src/vendor/io/pajek-parser.c" +#line 2309 "src/vendor/io/pajek-parser.c" break; case 93: /* edgeslist: "*Edgeslist line" "end of line" edgelistlines */ -#line 458 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 463 "src/vendor/cigraph/src/io/pajek-parser.y" { context->directed=0; } -#line 2310 "src/vendor/io/pajek-parser.c" +#line 2315 "src/vendor/io/pajek-parser.c" break; case 99: /* edgelistfrom: integer */ -#line 466 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 471 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actfrom=labs((yyvsp[0].intnum))-1; } -#line 2316 "src/vendor/io/pajek-parser.c" +#line 2321 "src/vendor/io/pajek-parser.c" break; case 100: /* edgelistto: integer */ -#line 468 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 473 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, context->actfrom)); IGRAPH_YY_CHECK(igraph_vector_int_push_back(context->vector, labs((yyvsp[0].intnum))-1)); } -#line 2325 "src/vendor/io/pajek-parser.c" +#line 2330 "src/vendor/io/pajek-parser.c" break; case 102: /* matrixline: "*Matrix line" */ -#line 477 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 482 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actfrom=0; context->actto=0; context->directed=(context->vcount2==0); } -#line 2334 "src/vendor/io/pajek-parser.c" +#line 2339 "src/vendor/io/pajek-parser.c" break; case 105: /* adjmatrixline: adjmatrixnumbers "end of line" */ -#line 484 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 489 "src/vendor/cigraph/src/io/pajek-parser.y" { context->actfrom++; context->actto=0; } -#line 2340 "src/vendor/io/pajek-parser.c" +#line 2345 "src/vendor/io/pajek-parser.c" break; case 108: /* adjmatrixentry: number */ -#line 488 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 493 "src/vendor/cigraph/src/io/pajek-parser.y" { if ((yyvsp[0].realnum) != 0) { if (context->vcount2==0) { @@ -2358,11 +2363,11 @@ YYLTYPE yylloc = yyloc_default; } context->actto++; } -#line 2362 "src/vendor/io/pajek-parser.c" +#line 2367 "src/vendor/io/pajek-parser.c" break; case 109: /* integer: "number" */ -#line 508 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 513 "src/vendor/cigraph/src/io/pajek-parser.y" { igraph_integer_t val; IGRAPH_YY_CHECK(igraph_i_parse_integer(igraph_pajek_yyget_text(scanner), @@ -2370,11 +2375,11 @@ YYLTYPE yylloc = yyloc_default; &val)); (yyval.intnum)=val; } -#line 2374 "src/vendor/io/pajek-parser.c" +#line 2379 "src/vendor/io/pajek-parser.c" break; case 110: /* number: "number" */ -#line 516 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 521 "src/vendor/cigraph/src/io/pajek-parser.y" { igraph_real_t val; IGRAPH_YY_CHECK(igraph_i_parse_real(igraph_pajek_yyget_text(scanner), @@ -2382,46 +2387,46 @@ YYLTYPE yylloc = yyloc_default; &val)); (yyval.realnum)=val; } -#line 2386 "src/vendor/io/pajek-parser.c" +#line 2391 "src/vendor/io/pajek-parser.c" break; case 111: /* parname: word */ -#line 524 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 529 "src/vendor/cigraph/src/io/pajek-parser.y" { IGRAPH_YY_CHECK(make_dynstr((yyvsp[0].string).str, (yyvsp[0].string).len, &(yyval.dynstr))); } -#line 2394 "src/vendor/io/pajek-parser.c" +#line 2399 "src/vendor/io/pajek-parser.c" break; case 112: /* parstrval: word */ -#line 528 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 533 "src/vendor/cigraph/src/io/pajek-parser.y" { (yyval.string)=(yyvsp[0].string); } -#line 2400 "src/vendor/io/pajek-parser.c" +#line 2405 "src/vendor/io/pajek-parser.c" break; case 113: /* word: "word" */ -#line 530 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 535 "src/vendor/cigraph/src/io/pajek-parser.y" { (yyval.string).str=igraph_pajek_yyget_text(scanner); (yyval.string).len=igraph_pajek_yyget_leng(scanner); } -#line 2407 "src/vendor/io/pajek-parser.c" +#line 2412 "src/vendor/io/pajek-parser.c" break; case 114: /* word: "number" */ -#line 532 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 537 "src/vendor/cigraph/src/io/pajek-parser.y" { (yyval.string).str=igraph_pajek_yyget_text(scanner); (yyval.string).len=igraph_pajek_yyget_leng(scanner); } -#line 2414 "src/vendor/io/pajek-parser.c" +#line 2419 "src/vendor/io/pajek-parser.c" break; case 115: /* word: "quoted string" */ -#line 534 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 539 "src/vendor/cigraph/src/io/pajek-parser.y" { (yyval.string).str=igraph_pajek_yyget_text(scanner)+1; (yyval.string).len=igraph_pajek_yyget_leng(scanner)-2; } -#line 2421 "src/vendor/io/pajek-parser.c" +#line 2426 "src/vendor/io/pajek-parser.c" break; -#line 2425 "src/vendor/io/pajek-parser.c" +#line 2430 "src/vendor/io/pajek-parser.c" default: break; } @@ -2650,7 +2655,7 @@ YYLTYPE yylloc = yyloc_default; return yyresult; } -#line 537 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 542 "src/vendor/cigraph/src/io/pajek-parser.y" int igraph_pajek_yyerror(YYLTYPE* locp, @@ -2665,49 +2670,38 @@ int igraph_pajek_yyerror(YYLTYPE* locp, /* TODO: NA's */ static igraph_error_t add_numeric_attribute(igraph_trie_t *names, - igraph_vector_ptr_t *attrs, + igraph_attribute_record_list_t *attrs, igraph_integer_t count, const char *attrname, + igraph_real_t default_value, igraph_integer_t elem_id, igraph_real_t number) { igraph_integer_t attrsize = igraph_trie_size(names); igraph_integer_t id; igraph_vector_t *na; - igraph_attribute_record_t *rec; + igraph_attribute_record_t *prec; IGRAPH_CHECK(igraph_trie_get(names, attrname, &id)); if (id == attrsize) { - /* add a new attribute */ - rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - CHECK_OOM_RP(rec); - IGRAPH_FINALLY(igraph_free, rec); + igraph_attribute_record_t rec; - na = IGRAPH_CALLOC(1, igraph_vector_t); - CHECK_OOM_RP(na); - IGRAPH_FINALLY(igraph_free, na); - IGRAPH_VECTOR_INIT_FINALLY(na, count); - - rec->name = strdup(attrname); - CHECK_OOM_RP(rec->name); - IGRAPH_FINALLY(igraph_free, (void *) rec->name); + /* add a new attribute */ + IGRAPH_CHECK(igraph_attribute_record_init(&rec, attrname, IGRAPH_ATTRIBUTE_NUMERIC)); + IGRAPH_FINALLY(igraph_attribute_record_destroy, &rec); - rec->type = IGRAPH_ATTRIBUTE_NUMERIC; - rec->value = na; + IGRAPH_CHECK(igraph_attribute_record_set_default_numeric(&rec, default_value)); - IGRAPH_CHECK(igraph_vector_ptr_push_back(attrs, rec)); - IGRAPH_FINALLY_CLEAN(4); /* ownership of rec transferred to attrs */ + IGRAPH_CHECK(igraph_attribute_record_resize(&rec, count)); + IGRAPH_CHECK(igraph_attribute_record_list_push_back(attrs, &rec)); + IGRAPH_FINALLY_CLEAN(1); /* ownership of rec transferred to attrs */ } - rec = VECTOR(*attrs)[id]; - na = (igraph_vector_t *) rec->value; + prec = igraph_attribute_record_list_get_ptr(attrs, id); + na = prec->value.as_vector; if (igraph_vector_size(na) == elem_id) { IGRAPH_CHECK(igraph_vector_push_back(na, number)); } else if (igraph_vector_size(na) < elem_id) { - igraph_integer_t origsize=igraph_vector_size(na); - IGRAPH_CHECK(igraph_vector_resize(na, elem_id+1)); - for (;origsizename = strdup(attrname); - CHECK_OOM_RP(rec->name); - IGRAPH_FINALLY(igraph_free, (char *) rec->name); + IGRAPH_CHECK(igraph_attribute_record_init(&rec, attrname, IGRAPH_ATTRIBUTE_STRING)); + IGRAPH_FINALLY(igraph_attribute_record_destroy, &rec); - rec->type = IGRAPH_ATTRIBUTE_STRING; - rec->value = na; + IGRAPH_CHECK(igraph_attribute_record_set_default_string(&rec, default_value)); - IGRAPH_CHECK(igraph_vector_ptr_push_back(attrs, rec)); - IGRAPH_FINALLY_CLEAN(4); /* ownership of rec transferred to attrs */ + IGRAPH_CHECK(igraph_attribute_record_resize(&rec, count)); + IGRAPH_CHECK(igraph_attribute_record_list_push_back(attrs, &rec)); + IGRAPH_FINALLY_CLEAN(1); /* ownership of rec transferred to attrs */ } - rec = VECTOR(*attrs)[id]; - na = (igraph_strvector_t *) rec->value; + prec = igraph_attribute_record_list_get_ptr(attrs, id); + na = prec->value.as_strvector; if (igraph_strvector_size(na) <= elem_id) { IGRAPH_CHECK(igraph_strvector_resize(na, elem_id+1)); } @@ -2792,7 +2775,9 @@ static igraph_error_t add_string_vertex_attribute(const char *name, return add_string_attribute(context->vertex_attribute_names, context->vertex_attributes, context->vcount, - name, context->actvertex-1, + name, + get_default_value_for_string_vattr(name), + context->actvertex-1, value, len); } @@ -2804,7 +2789,9 @@ static igraph_error_t add_string_edge_attribute(const char *name, return add_string_attribute(context->edge_attribute_names, context->edge_attributes, context->actedge, - name, context->actedge-1, + name, + get_default_value_for_string_eattr(name), + context->actedge-1, value, len); } @@ -2815,7 +2802,9 @@ static igraph_error_t add_numeric_vertex_attribute(const char *name, return add_numeric_attribute(context->vertex_attribute_names, context->vertex_attributes, context->vcount, - name, context->actvertex-1, + name, + get_default_value_for_numeric_vattr(name), + context->actvertex-1, value); } @@ -2826,7 +2815,9 @@ static igraph_error_t add_numeric_edge_attribute(const char *name, return add_numeric_attribute(context->edge_attribute_names, context->edge_attributes, context->actedge, - name, context->actedge-1, + name, + get_default_value_for_numeric_eattr(name), + context->actedge-1, value); } @@ -2834,10 +2825,10 @@ static igraph_error_t add_bipartite_type(igraph_i_pajek_parsedata_t *context) { const char *attrname="type"; igraph_trie_t *names=context->vertex_attribute_names; - igraph_vector_ptr_t *attrs=context->vertex_attributes; + igraph_attribute_record_list_t *attrs=context->vertex_attributes; igraph_integer_t n=context->vcount, n1=context->vcount2; igraph_integer_t attrid, attrsize = igraph_trie_size(names); - igraph_attribute_record_t *rec; + igraph_attribute_record_t* rec; igraph_vector_bool_t *na; if (n1 > n) { @@ -2852,29 +2843,13 @@ static igraph_error_t add_bipartite_type(igraph_i_pajek_parsedata_t *context) { IGRAPH_ASSERT(attrid == attrsize); /* add a new attribute */ - rec = IGRAPH_CALLOC(1, igraph_attribute_record_t); - CHECK_OOM_RP(rec); - IGRAPH_FINALLY(igraph_free, rec); + IGRAPH_CHECK(igraph_attribute_record_list_push_back_new(attrs, &rec)); + IGRAPH_CHECK(igraph_attribute_record_set_name(rec, attrname)); + IGRAPH_CHECK(igraph_attribute_record_set_type(rec, IGRAPH_ATTRIBUTE_BOOLEAN)); + IGRAPH_CHECK(igraph_attribute_record_resize(rec, n)); - na = IGRAPH_CALLOC(1, igraph_vector_bool_t); - CHECK_OOM_RP(na); - IGRAPH_FINALLY(igraph_free, na); - IGRAPH_VECTOR_BOOL_INIT_FINALLY(na, n); - - rec->name = strdup(attrname); - CHECK_OOM_RP(rec->name); - IGRAPH_FINALLY(igraph_free, (char *) rec->name); - - rec->type = IGRAPH_ATTRIBUTE_BOOLEAN; - rec->value = na; - - IGRAPH_CHECK(igraph_vector_ptr_push_back(attrs, rec)); - IGRAPH_FINALLY_CLEAN(4); /* ownership of 'rec' transferred to 'attrs' */ - - for (igraph_integer_t i=0; ivalue.as_vector_bool; + for (igraph_integer_t i = n1; i < n; i++) { VECTOR(*na)[i] = true; } @@ -2914,7 +2889,7 @@ static igraph_bool_t is_standard_vattr(const char *attrname) { "font", "url", "color", "framecolor", "labelcolor" }; - for (size_t i=0; i < sizeof(names) / sizeof(names[0]); i++) { + for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); i++) { if (strcmp(attrname, names[i]) == 0) { return true; } @@ -2956,3 +2931,108 @@ static igraph_error_t deconflict_attrname(char **attrname) { *attrname = tmp; return IGRAPH_SUCCESS; } + +typedef struct { + const char* name; + igraph_real_t default_value; +} attribute_numeric_defaults_t; + +typedef struct { + const char* name; + const char* default_value; +} attribute_string_defaults_t; + +/* The defaults listed below are Pajek's built-in defaults unless the user + * overrides them. + * + * See: https://nascol.discourse.group/t/pajek-file-format-default-values-for-attributes/38/2 + */ + +const attribute_numeric_defaults_t vattr_numeric_defaults[] = { + { "xfact", 1 }, + { "yfact", 1 }, + { "labeldist", 20 }, + { "labeldegree2", 285 }, + { "framewidth", 1 }, + { "fontsize", 15 }, + { "rotation", 0 }, + { "radius", 0 }, + { "diamondratio", 0.01 }, + { "labeldegree", 0 }, + { 0 } +}; + +const attribute_string_defaults_t vattr_string_defaults[] = { + { "color", "LightOrange" }, + { "framecolor", "Brown" }, + { "labelcolor", "Maroon" }, + { 0 } +}; + +const attribute_numeric_defaults_t eattr_numeric_defaults[] = { + { "arrowsize", 1 }, + { "edgewidth", 2 }, + { "hook1", 0 }, + { "hook2", 0 }, + { "angle1", 0 }, + { "angle2", 0 }, + { "velocity1", 1 }, + { "velocity2", 1 }, + { "arrowpos", 0 }, + { "labelpos", 0.5 }, + { "labelangle", 10 }, + { "labelangle2", 90 }, + { "labeldegree", 0 }, + { "fontsize", 15 }, + { 0 } +}; + +const attribute_string_defaults_t eattr_string_defaults[] = { + { "color", "MidnightBlue" }, + { "labelcolor", "Black" }, + { 0 } +}; + +static igraph_real_t get_default_value_for_numeric_attr( + const char *attrname, const attribute_numeric_defaults_t* table +) { + const attribute_numeric_defaults_t* ptr; + + for (ptr = table; ptr->name != 0; ptr++) { + if (!strcmp(attrname, ptr->name)) { + return ptr->default_value; + } + } + + return IGRAPH_NAN; +} + +static const char* get_default_value_for_string_attr( + const char *attrname, const attribute_string_defaults_t* table +) { + const attribute_string_defaults_t* ptr; + + for (ptr = table; ptr->name != 0; ptr++) { + if (!strcmp(attrname, ptr->name)) { + return ptr->default_value; + } + } + + return ""; +} + +static igraph_real_t get_default_value_for_numeric_vattr(const char *attrname) { + return get_default_value_for_numeric_attr(attrname, vattr_numeric_defaults); +} + +static igraph_real_t get_default_value_for_numeric_eattr(const char *attrname) { + return get_default_value_for_numeric_attr(attrname, eattr_numeric_defaults); +} + +static const char* get_default_value_for_string_vattr(const char *attrname) { + return get_default_value_for_string_attr(attrname, vattr_string_defaults); +} + +static const char* get_default_value_for_string_eattr(const char *attrname) { + return get_default_value_for_string_attr(attrname, eattr_string_defaults); +} diff --git a/src/vendor/io/parsers/pajek-parser.h b/src/vendor/io/parsers/pajek-parser.h index 79385e2e367..64ada07751d 100644 --- a/src/vendor/io/parsers/pajek-parser.h +++ b/src/vendor/io/parsers/pajek-parser.h @@ -109,7 +109,7 @@ extern int igraph_pajek_yydebug; #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { -#line 116 "src/vendor/cigraph/src/io/pajek-parser.y" +#line 122 "src/vendor/cigraph/src/io/pajek-parser.y" igraph_integer_t intnum; igraph_real_t realnum; diff --git a/tests/testthat/test-canonical.permutation.R b/tests/testthat/test-canonical.permutation.R index a6d86155910..ed557d10d1a 100644 --- a/tests/testthat/test-canonical.permutation.R +++ b/tests/testthat/test-canonical.permutation.R @@ -1,12 +1,12 @@ test_that("canonical_permutation works", { g1 <- sample_gnm(10, 20) cp1 <- canonical_permutation(g1) - cf1 <- permute(g1, cp1$labeling) + cf1 <- permute(g1, cp1) ## Do the same with a random permutation of it g2 <- permute(g1, sample(vcount(g1))) cp2 <- canonical_permutation(g2) - cf2 <- permute(g2, cp2$labeling) + cf2 <- permute(g2, cp2) ## Check that they are the same el1 <- as_edgelist(cf1) diff --git a/tests/testthat/test-topology.R b/tests/testthat/test-topology.R index 57101b07016..e0a5e0a584f 100644 --- a/tests/testthat/test-topology.R +++ b/tests/testthat/test-topology.R @@ -1,19 +1,19 @@ test_that("automorphisms works", { g <- make_ring(10) - expect_that(count_automorphisms(g)$group_size, equals("20")) + expect_that(count_automorphisms(g), equals(20)) g <- make_full_graph(4) - expect_that(count_automorphisms(g)$group_size, equals("24")) + expect_that(count_automorphisms(g), equals(24)) }) test_that("automorphisms works with colored graphs", { g <- make_full_graph(4) - expect_that(count_automorphisms(g, colors = c(1, 2, 1, 2))$group_size, equals("4")) + expect_that(count_automorphisms(g, colors = c(1, 2, 1, 2)), equals(4)) V(g)$color <- c(1, 2, 1, 2) - expect_that(count_automorphisms(g)$group_size, equals("4")) - expect_that(count_automorphisms(g, colors = NULL)$group_size, equals("24")) + expect_that(count_automorphisms(g), equals(4)) + expect_that(count_automorphisms(g, colors = NULL), equals(24)) }) diff --git a/tools/stimulus/functions-R.yaml b/tools/stimulus/functions-R.yaml index e70242eacbd..0bffcef9e16 100644 --- a/tools/stimulus/functions-R.yaml +++ b/tools/stimulus/functions-R.yaml @@ -29,8 +29,6 @@ igraph_delete_edges: igraph_delete_vertices: IGNORE: RR, RC -igraph_delete_vertices_idx: - igraph_vcount: igraph_ecount: @@ -423,8 +421,6 @@ igraph_edge_betweenness: igraph_edge_betweenness_cutoff: IGNORE: RR -igraph_edge_betweenness_subset: - igraph_harmonic_centrality: IGNORE: RR, RC, RInit # This is handled by igraph_harmonic_centrality_cutoff @@ -561,6 +557,13 @@ igraph_hub_and_authority_scores: # in the argument list. DEPS: weights ON graph, hub_vector ON graph V(graph), authority_vector ON graph V(graph) +igraph_edge_betweenness_subset: + # This is a temporary hack; we need to find a way to handle default values + # for dependencies. The problem is that the VERTEXINDEX type needs two + # dependencies: the graph and the vertex set, but we only have the graph + # in the argument list. + DEPS: eids ON graph, weights ON graph, res ON graph V(graph), sources ON graph, targets ON graph + igraph_unfold_tree: IGNORE: RR diff --git a/tools/stimulus/types-RC.yaml b/tools/stimulus/types-RC.yaml index c42e290b3c3..dd1375dbb00 100644 --- a/tools/stimulus/types-RC.yaml +++ b/tools/stimulus/types-RC.yaml @@ -231,7 +231,7 @@ VECTOR_INT_LIST: igraph_vector_int_list_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); -VERTEXSET_LIST: +VERTEX_INDICES_LIST: CALL: '&%C%' CTYPE: igraph_vector_int_list_t INCONV: @@ -252,7 +252,7 @@ VERTEXSET_LIST: igraph_vector_int_list_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); -EDGESET_LIST: +EDGE_INDICES_LIST: CALL: '&%C%' CTYPE: igraph_vector_int_list_t INCONV: @@ -304,7 +304,7 @@ ADJLIST: OUTCONV: IN: igraph_adjlist_destroy(&%C%); -EDGEWEIGHTS: +EDGE_WEIGHTS: CALL: '(Rf_isNull(%I%) ? 0 : &%C%)' CTYPE: igraph_vector_t INCONV: @@ -321,7 +321,7 @@ EDGEWEIGHTS: igraph_vector_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); -VERTEXWEIGHTS: +VERTEX_WEIGHTS: CALL: '(Rf_isNull(%I%) ? 0 : &%C%)' CTYPE: igraph_vector_t INCONV: @@ -338,7 +338,7 @@ VERTEXWEIGHTS: igraph_vector_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); -EDGE_CAPACITY: +EDGE_CAPACITIES: CALL: '(Rf_isNull(%I%) ? 0 : &%C%)' CTYPE: igraph_vector_t INCONV: @@ -448,7 +448,7 @@ VERTEX_ROOT: PROTECT(%I% = NEW_INTEGER(1)); INTEGER(%I%)[0] = %C% + 1; -VERTEX_QTY: +VERTEX_QTYS: CALL: '&%C%' CTYPE: igraph_vector_t INCONV: @@ -587,14 +587,14 @@ ATTRIBUTES: CTYPE: ~ HEADER: {} -ARPACKOPT: +ARPACK_OPTIONS: CALL: '&%C%' INCONV: INOUT: R_SEXP_to_igraph_arpack_options(%I%, &%C%); OUTCONV: INOUT: PROTECT(%I%=R_igraph_arpack_options_to_SEXP(&%C%)); -ARPACKSTORAGE: +ARPACK_STORAGE: CALL: '0' CTYPE: ~ HEADER: {} @@ -650,7 +650,7 @@ BIPARTITE_TYPES: igraph_vector_bool_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); -VERTEX_COLOR: +VERTEX_COLORS: CALL: IN: '(Rf_isNull(%I%) ? 0 : &%C%)' OUT: '&%C%' @@ -677,7 +677,7 @@ VERTEX_COLOR: igraph_vector_int_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); -EDGE_COLOR: +EDGE_COLORS: CALL: IN: '(Rf_isNull(%I%) ? 0 : &%C%)' OUT: '&%C%' diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index d39c49aaaf9..1cb6ee60731 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -32,7 +32,7 @@ VECTOR: AsmDefaultCvec: strength(%I1%, weights=weights)/(vcount(%I1%)-1) INCONV: '%I% <- as.numeric(%I%)' -VERTEX_QTY: +VERTEX_QTYS: OUTCONV: OUT: |- if (igraph_opt("add.vertex.names") && is_named(%I1%)) { @@ -156,7 +156,7 @@ EDGE_SELECTOR: %I% <- create_es(%I1%, %I%) } -EDGEWEIGHTS: +EDGE_WEIGHTS: INCONV: |- if (is.null(%I%) && "weight" %in% edge_attr_names(%I1%)) { %I% <- E(%I1%)$weight @@ -167,7 +167,7 @@ EDGEWEIGHTS: %I% <- NULL } -VERTEXWEIGHTS: +VERTEX_WEIGHTS: INCONV: |- if (is.null(%I%) && "weight" %in% vertex_attr_names(%I1%)) { %I% <- V(%I1%)$weight @@ -178,7 +178,7 @@ VERTEXWEIGHTS: %I% <- NULL } -EDGE_CAPACITY: +EDGE_CAPACITIES: INCONV: |- if (is.null(%I%) && "capacity" %in% edge_attr_names(%I1%)) { %I% <- E(%I1%)$capacity @@ -198,7 +198,7 @@ BIPARTITE_TYPES: names(%I%) <- vertex_attr(%I1%, "name", %I2%) } -VERTEX_COLOR: +VERTEX_COLORS: INCONV: |- if (missing(%I%)) { if ("color" %in% vertex_attr_names(%I1%)) { @@ -217,7 +217,7 @@ VERTEX_COLOR: names(%I%) <- vertex_attr(%I1%, "name") } -EDGE_COLOR: +EDGE_COLORS: INCONV: |- if (missing(%I%)) { if ("color" %in% edge_attr_names(%I1%)) { @@ -245,25 +245,25 @@ ISOCOMPAT_FUNC: CALL: {} HEADER: ~ -VERTEXSET_LIST: +VERTEX_INDICES_LIST: OUTCONV: OUT: |- if (igraph_opt("return.vs.es")) { %I% <- lapply(%I%, unsafe_create_vs, graph = %I1%, verts = V(%I1%)) } -EDGESET_LIST: +EDGE_INDICES_LIST: OUTCONV: OUT: |- if (igraph_opt("return.vs.es")) { %I% <- lapply(%I%, unsafe_create_es, graph = %I1%, es = E(%I1%)) } -'ARPACKSTORAGE': +'ARPACK_STORAGE': CALL: {} HEADER: ~ -ARPACKOPT: +ARPACK_OPTIONS: DEFAULT: ARPACK_DEFAULTS: arpack_defaults() INCONV: